xref: /aosp_15_r20/external/webrtc/net/dcsctp/packet/chunk/iforward_tsn_chunk.cc (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 #include "net/dcsctp/packet/chunk/iforward_tsn_chunk.h"
11 
12 #include <stddef.h>
13 #include <stdint.h>
14 
15 #include <string>
16 #include <utility>
17 #include <vector>
18 
19 #include "absl/types/optional.h"
20 #include "api/array_view.h"
21 #include "net/dcsctp/packet/bounded_byte_reader.h"
22 #include "net/dcsctp/packet/bounded_byte_writer.h"
23 #include "net/dcsctp/packet/chunk/forward_tsn_common.h"
24 #include "net/dcsctp/packet/tlv_trait.h"
25 #include "rtc_base/strings/string_builder.h"
26 
27 namespace dcsctp {
28 
29 // https://tools.ietf.org/html/rfc8260#section-2.3.1
30 
31 //   0                   1                   2                   3
32 //   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
33 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34 //  |   Type = 194  | Flags = 0x00  |      Length = Variable        |
35 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36 //  |                       New Cumulative TSN                      |
37 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
38 //  |       Stream Identifier       |          Reserved           |U|
39 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40 //  |                       Message Identifier                      |
41 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42 //  \                                                               \
43 //  /                                                               /
44 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 //  |       Stream Identifier       |          Reserved           |U|
46 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47 //  |                       Message Identifier                      |
48 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49 constexpr int IForwardTsnChunk::kType;
50 
Parse(rtc::ArrayView<const uint8_t> data)51 absl::optional<IForwardTsnChunk> IForwardTsnChunk::Parse(
52     rtc::ArrayView<const uint8_t> data) {
53   absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
54   if (!reader.has_value()) {
55     return absl::nullopt;
56   }
57 
58   TSN new_cumulative_tsn(reader->Load32<4>());
59 
60   size_t streams_skipped =
61       reader->variable_data_size() / kSkippedStreamBufferSize;
62   std::vector<SkippedStream> skipped_streams;
63   skipped_streams.reserve(streams_skipped);
64   size_t offset = 0;
65   for (size_t i = 0; i < streams_skipped; ++i) {
66     BoundedByteReader<kSkippedStreamBufferSize> sub_reader =
67         reader->sub_reader<kSkippedStreamBufferSize>(offset);
68 
69     StreamID stream_id(sub_reader.Load16<0>());
70     IsUnordered unordered(sub_reader.Load8<3>() & 0x01);
71     MID message_id(sub_reader.Load32<4>());
72     skipped_streams.emplace_back(unordered, stream_id, message_id);
73     offset += kSkippedStreamBufferSize;
74   }
75   RTC_DCHECK(offset == reader->variable_data_size());
76   return IForwardTsnChunk(new_cumulative_tsn, std::move(skipped_streams));
77 }
78 
SerializeTo(std::vector<uint8_t> & out) const79 void IForwardTsnChunk::SerializeTo(std::vector<uint8_t>& out) const {
80   rtc::ArrayView<const SkippedStream> skipped = skipped_streams();
81   size_t variable_size = skipped.size() * kSkippedStreamBufferSize;
82   BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, variable_size);
83 
84   writer.Store32<4>(*new_cumulative_tsn());
85   size_t offset = 0;
86   for (size_t i = 0; i < skipped.size(); ++i) {
87     BoundedByteWriter<kSkippedStreamBufferSize> sub_writer =
88         writer.sub_writer<kSkippedStreamBufferSize>(offset);
89 
90     sub_writer.Store16<0>(*skipped[i].stream_id);
91     sub_writer.Store8<3>(skipped[i].unordered ? 1 : 0);
92     sub_writer.Store32<4>(*skipped[i].message_id);
93     offset += kSkippedStreamBufferSize;
94   }
95   RTC_DCHECK(offset == variable_size);
96 }
97 
ToString() const98 std::string IForwardTsnChunk::ToString() const {
99   rtc::StringBuilder sb;
100   sb << "I-FORWARD-TSN, new_cumulative_tsn=" << *new_cumulative_tsn();
101   return sb.Release();
102 }
103 
104 }  // namespace dcsctp
105