xref: /aosp_15_r20/external/webrtc/net/dcsctp/rx/traditional_reassembly_streams.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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