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_INTERLEAVED_REASSEMBLY_STREAMS_H_ 11 #define NET_DCSCTP_RX_INTERLEAVED_REASSEMBLY_STREAMS_H_ 12 13 #include <cstdint> 14 #include <map> 15 #include <string> 16 #include <utility> 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 is 28 // enabled on the association, i.e. when RFC8260 is in use. 29 class InterleavedReassemblyStreams : public ReassemblyStreams { 30 public: 31 InterleavedReassemblyStreams(absl::string_view log_prefix, 32 OnAssembledMessage on_assembled_message); 33 34 int Add(UnwrappedTSN tsn, Data data) override; 35 36 size_t HandleForwardTsn( 37 UnwrappedTSN new_cumulative_ack_tsn, 38 rtc::ArrayView<const AnyForwardTsnChunk::SkippedStream> skipped_streams) 39 override; 40 41 void ResetStreams(rtc::ArrayView<const StreamID> stream_ids) override; 42 43 HandoverReadinessStatus GetHandoverReadiness() const override; 44 void AddHandoverState(DcSctpSocketHandoverState& state) override; 45 void RestoreFromState(const DcSctpSocketHandoverState& state) override; 46 47 private: 48 struct FullStreamId { 49 const IsUnordered unordered; 50 const StreamID stream_id; 51 FullStreamIdFullStreamId52 FullStreamId(IsUnordered unordered, StreamID stream_id) 53 : unordered(unordered), stream_id(stream_id) {} 54 55 friend bool operator<(FullStreamId a, FullStreamId b) { 56 return a.unordered < b.unordered || 57 (!(a.unordered < b.unordered) && (a.stream_id < b.stream_id)); 58 } 59 }; 60 61 class Stream { 62 public: 63 Stream(FullStreamId stream_id, 64 InterleavedReassemblyStreams* parent, 65 MID next_mid = MID(0)) stream_id_(stream_id)66 : stream_id_(stream_id), 67 parent_(*parent), 68 next_mid_(mid_unwrapper_.Unwrap(next_mid)) {} 69 int Add(UnwrappedTSN tsn, Data data); 70 size_t EraseTo(MID message_id); Reset()71 void Reset() { 72 mid_unwrapper_.Reset(); 73 next_mid_ = mid_unwrapper_.Unwrap(MID(0)); 74 } has_unassembled_chunks()75 bool has_unassembled_chunks() const { return !chunks_by_mid_.empty(); } 76 void AddHandoverState(DcSctpSocketHandoverState& state) const; 77 78 private: 79 using ChunkMap = std::map<FSN, std::pair<UnwrappedTSN, Data>>; 80 81 // Try to assemble one message identified by `mid`. 82 // Returns the number of bytes assembled if a message was assembled. 83 size_t TryToAssembleMessage(UnwrappedMID mid); 84 size_t AssembleMessage(const ChunkMap& tsn_chunks); 85 // Try to assemble one or several messages in order from the stream. 86 // Returns the number of bytes assembled if one or more messages were 87 // assembled. 88 size_t TryToAssembleMessages(); 89 90 const FullStreamId stream_id_; 91 InterleavedReassemblyStreams& parent_; 92 std::map<UnwrappedMID, ChunkMap> chunks_by_mid_; 93 UnwrappedMID::Unwrapper mid_unwrapper_; 94 UnwrappedMID next_mid_; 95 }; 96 97 Stream& GetOrCreateStream(const FullStreamId& stream_id); 98 99 const std::string log_prefix_; 100 101 // Callback for when a message has been assembled. 102 const OnAssembledMessage on_assembled_message_; 103 104 // All unordered and ordered streams, managing not-yet-assembled data. 105 std::map<FullStreamId, Stream> streams_; 106 }; 107 108 } // namespace dcsctp 109 110 #endif // NET_DCSCTP_RX_INTERLEAVED_REASSEMBLY_STREAMS_H_ 111