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/init_chunk.h"
11
12 #include <stdint.h>
13
14 #include <string>
15 #include <utility>
16 #include <vector>
17
18 #include "absl/types/optional.h"
19 #include "api/array_view.h"
20 #include "net/dcsctp/packet/bounded_byte_reader.h"
21 #include "net/dcsctp/packet/bounded_byte_writer.h"
22 #include "net/dcsctp/packet/parameter/parameter.h"
23 #include "net/dcsctp/packet/tlv_trait.h"
24 #include "rtc_base/strings/string_format.h"
25
26 namespace dcsctp {
27
28 // https://tools.ietf.org/html/rfc4960#section-3.3.2
29
30 // 0 1 2 3
31 // 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
32 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33 // | Type = 1 | Chunk Flags | Chunk Length |
34 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35 // | Initiate Tag |
36 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37 // | Advertised Receiver Window Credit (a_rwnd) |
38 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39 // | Number of Outbound Streams | Number of Inbound Streams |
40 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41 // | Initial TSN |
42 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43 // \ \
44 // / Optional/Variable-Length Parameters /
45 // \ \
46 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47 constexpr int InitChunk::kType;
48
Parse(rtc::ArrayView<const uint8_t> data)49 absl::optional<InitChunk> InitChunk::Parse(rtc::ArrayView<const uint8_t> data) {
50 absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
51 if (!reader.has_value()) {
52 return absl::nullopt;
53 }
54
55 VerificationTag initiate_tag(reader->Load32<4>());
56 uint32_t a_rwnd = reader->Load32<8>();
57 uint16_t nbr_outbound_streams = reader->Load16<12>();
58 uint16_t nbr_inbound_streams = reader->Load16<14>();
59 TSN initial_tsn(reader->Load32<16>());
60
61 absl::optional<Parameters> parameters =
62 Parameters::Parse(reader->variable_data());
63 if (!parameters.has_value()) {
64 return absl::nullopt;
65 }
66 return InitChunk(initiate_tag, a_rwnd, nbr_outbound_streams,
67 nbr_inbound_streams, initial_tsn, *std::move(parameters));
68 }
69
SerializeTo(std::vector<uint8_t> & out) const70 void InitChunk::SerializeTo(std::vector<uint8_t>& out) const {
71 rtc::ArrayView<const uint8_t> parameters = parameters_.data();
72 BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, parameters.size());
73
74 writer.Store32<4>(*initiate_tag_);
75 writer.Store32<8>(a_rwnd_);
76 writer.Store16<12>(nbr_outbound_streams_);
77 writer.Store16<14>(nbr_inbound_streams_);
78 writer.Store32<16>(*initial_tsn_);
79
80 writer.CopyToVariableData(parameters);
81 }
82
ToString() const83 std::string InitChunk::ToString() const {
84 return rtc::StringFormat("INIT, initiate_tag=0x%0x, initial_tsn=%u",
85 *initiate_tag(), *initial_tsn());
86 }
87
88 } // namespace dcsctp
89