1 /* 2 * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 #ifndef NET_DCSCTP_RX_TRADITIONAL_REASSEMBLY_STREAMS_H_ 11 #define NET_DCSCTP_RX_TRADITIONAL_REASSEMBLY_STREAMS_H_ 12 #include <stddef.h> 13 #include <stdint.h> 14 15 #include <map> 16 #include <string> 17 18 #include "absl/strings/string_view.h" 19 #include "api/array_view.h" 20 #include "net/dcsctp/common/sequence_numbers.h" 21 #include "net/dcsctp/packet/chunk/forward_tsn_common.h" 22 #include "net/dcsctp/packet/data.h" 23 #include "net/dcsctp/rx/reassembly_streams.h" 24 25 namespace dcsctp { 26 27 // Handles reassembly of incoming data when interleaved message sending 28 // is not enabled on the association, i.e. when RFC8260 is not in use and 29 // RFC4960 is to be followed. 30 class TraditionalReassemblyStreams : public ReassemblyStreams { 31 public: 32 TraditionalReassemblyStreams(absl::string_view log_prefix, 33 OnAssembledMessage on_assembled_message); 34 35 int Add(UnwrappedTSN tsn, Data data) override; 36 37 size_t HandleForwardTsn( 38 UnwrappedTSN new_cumulative_ack_tsn, 39 rtc::ArrayView<const AnyForwardTsnChunk::SkippedStream> skipped_streams) 40 override; 41 42 void ResetStreams(rtc::ArrayView<const StreamID> stream_ids) override; 43 44 HandoverReadinessStatus GetHandoverReadiness() const override; 45 void AddHandoverState(DcSctpSocketHandoverState& state) override; 46 void RestoreFromState(const DcSctpSocketHandoverState& state) override; 47 48 private: 49 using ChunkMap = std::map<UnwrappedTSN, Data>; 50 51 // Base class for `UnorderedStream` and `OrderedStream`. 52 class StreamBase { 53 protected: StreamBase(TraditionalReassemblyStreams * parent)54 explicit StreamBase(TraditionalReassemblyStreams* parent) 55 : parent_(*parent) {} 56 57 size_t AssembleMessage(ChunkMap::iterator start, ChunkMap::iterator end); 58 TraditionalReassemblyStreams& parent_; 59 }; 60 61 // Manages all received data for a specific unordered stream, and assembles 62 // messages when possible. 63 class UnorderedStream : StreamBase { 64 public: UnorderedStream(TraditionalReassemblyStreams * parent)65 explicit UnorderedStream(TraditionalReassemblyStreams* parent) 66 : StreamBase(parent) {} 67 int Add(UnwrappedTSN tsn, Data data); 68 // Returns the number of bytes removed from the queue. 69 size_t EraseTo(UnwrappedTSN tsn); has_unassembled_chunks()70 bool has_unassembled_chunks() const { return !chunks_.empty(); } 71 72 private: 73 // Given an iterator to any chunk within the map, try to assemble a message 74 // into `reassembled_messages` containing it and - if successful - erase 75 // those chunks from the stream chunks map. 76 // 77 // Returns the number of bytes that were assembled. 78 size_t TryToAssembleMessage(ChunkMap::iterator iter); 79 80 ChunkMap chunks_; 81 }; 82 83 // Manages all received data for a specific ordered stream, and assembles 84 // messages when possible. 85 class OrderedStream : StreamBase { 86 public: 87 explicit OrderedStream(TraditionalReassemblyStreams* parent, 88 SSN next_ssn = SSN(0)) StreamBase(parent)89 : StreamBase(parent), next_ssn_(ssn_unwrapper_.Unwrap(next_ssn)) {} 90 int Add(UnwrappedTSN tsn, Data data); 91 size_t EraseTo(SSN ssn); Reset()92 void Reset() { 93 ssn_unwrapper_.Reset(); 94 next_ssn_ = ssn_unwrapper_.Unwrap(SSN(0)); 95 } next_ssn()96 SSN next_ssn() const { return next_ssn_.Wrap(); } has_unassembled_chunks()97 bool has_unassembled_chunks() const { return !chunks_by_ssn_.empty(); } 98 99 private: 100 // Try to assemble one or several messages in order from the stream. 101 // Returns the number of bytes assembled if a message was assembled. 102 size_t TryToAssembleMessage(); 103 size_t TryToAssembleMessages(); 104 // This must be an ordered container to be able to iterate in SSN order. 105 std::map<UnwrappedSSN, ChunkMap> chunks_by_ssn_; 106 UnwrappedSSN::Unwrapper ssn_unwrapper_; 107 UnwrappedSSN next_ssn_; 108 }; 109 110 const std::string log_prefix_; 111 112 // Callback for when a message has been assembled. 113 const OnAssembledMessage on_assembled_message_; 114 115 // All unordered and ordered streams, managing not-yet-assembled data. 116 std::map<StreamID, UnorderedStream> unordered_streams_; 117 std::map<StreamID, OrderedStream> ordered_streams_; 118 }; 119 120 } // namespace dcsctp 121 122 #endif // NET_DCSCTP_RX_TRADITIONAL_REASSEMBLY_STREAMS_H_ 123