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/parameter/reconfiguration_response_parameter.h" 11 12 #include <stddef.h> 13 #include <stdint.h> 14 15 #include <string> 16 #include <type_traits> 17 #include <vector> 18 19 #include "absl/strings/string_view.h" 20 #include "absl/types/optional.h" 21 #include "api/array_view.h" 22 #include "net/dcsctp/packet/bounded_byte_reader.h" 23 #include "net/dcsctp/packet/bounded_byte_writer.h" 24 #include "net/dcsctp/packet/tlv_trait.h" 25 #include "rtc_base/logging.h" 26 #include "rtc_base/strings/string_builder.h" 27 28 namespace dcsctp { 29 30 // https://tools.ietf.org/html/rfc6525#section-4.4 31 32 // 0 1 2 3 33 // 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 34 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 35 // | Parameter Type = 16 | Parameter Length | 36 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 37 // | Re-configuration Response Sequence Number | 38 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 39 // | Result | 40 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 41 // | Sender's Next TSN (optional) | 42 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 43 // | Receiver's Next TSN (optional) | 44 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 45 constexpr int ReconfigurationResponseParameter::kType; 46 ToString(ReconfigurationResponseParameter::Result result)47absl::string_view ToString(ReconfigurationResponseParameter::Result result) { 48 switch (result) { 49 case ReconfigurationResponseParameter::Result::kSuccessNothingToDo: 50 return "Success: nothing to do"; 51 case ReconfigurationResponseParameter::Result::kSuccessPerformed: 52 return "Success: performed"; 53 case ReconfigurationResponseParameter::Result::kDenied: 54 return "Denied"; 55 case ReconfigurationResponseParameter::Result::kErrorWrongSSN: 56 return "Error: wrong ssn"; 57 case ReconfigurationResponseParameter::Result:: 58 kErrorRequestAlreadyInProgress: 59 return "Error: request already in progress"; 60 case ReconfigurationResponseParameter::Result::kErrorBadSequenceNumber: 61 return "Error: bad sequence number"; 62 case ReconfigurationResponseParameter::Result::kInProgress: 63 return "In progress"; 64 } 65 } 66 67 absl::optional<ReconfigurationResponseParameter> Parse(rtc::ArrayView<const uint8_t> data)68ReconfigurationResponseParameter::Parse(rtc::ArrayView<const uint8_t> data) { 69 absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data); 70 if (!reader.has_value()) { 71 return absl::nullopt; 72 } 73 74 ReconfigRequestSN response_sequence_number(reader->Load32<4>()); 75 Result result; 76 uint32_t result_nbr = reader->Load32<8>(); 77 switch (result_nbr) { 78 case 0: 79 result = ReconfigurationResponseParameter::Result::kSuccessNothingToDo; 80 break; 81 case 1: 82 result = ReconfigurationResponseParameter::Result::kSuccessPerformed; 83 break; 84 case 2: 85 result = ReconfigurationResponseParameter::Result::kDenied; 86 break; 87 case 3: 88 result = ReconfigurationResponseParameter::Result::kErrorWrongSSN; 89 break; 90 case 4: 91 result = ReconfigurationResponseParameter::Result:: 92 kErrorRequestAlreadyInProgress; 93 break; 94 case 5: 95 result = 96 ReconfigurationResponseParameter::Result::kErrorBadSequenceNumber; 97 break; 98 case 6: 99 result = ReconfigurationResponseParameter::Result::kInProgress; 100 break; 101 default: 102 RTC_DLOG(LS_WARNING) << "Invalid reconfig response result: " 103 << result_nbr; 104 return absl::nullopt; 105 } 106 107 if (reader->variable_data().empty()) { 108 return ReconfigurationResponseParameter(response_sequence_number, result); 109 } else if (reader->variable_data_size() != kNextTsnHeaderSize) { 110 RTC_DLOG(LS_WARNING) << "Invalid parameter size"; 111 return absl::nullopt; 112 } 113 114 BoundedByteReader<kNextTsnHeaderSize> sub_reader = 115 reader->sub_reader<kNextTsnHeaderSize>(0); 116 117 TSN sender_next_tsn(sub_reader.Load32<0>()); 118 TSN receiver_next_tsn(sub_reader.Load32<4>()); 119 120 return ReconfigurationResponseParameter(response_sequence_number, result, 121 sender_next_tsn, receiver_next_tsn); 122 } 123 SerializeTo(std::vector<uint8_t> & out) const124void ReconfigurationResponseParameter::SerializeTo( 125 std::vector<uint8_t>& out) const { 126 size_t variable_size = 127 (sender_next_tsn().has_value() ? kNextTsnHeaderSize : 0); 128 BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, variable_size); 129 130 writer.Store32<4>(*response_sequence_number_); 131 uint32_t result_nbr = 132 static_cast<std::underlying_type<Result>::type>(result_); 133 writer.Store32<8>(result_nbr); 134 135 if (sender_next_tsn().has_value()) { 136 BoundedByteWriter<kNextTsnHeaderSize> sub_writer = 137 writer.sub_writer<kNextTsnHeaderSize>(0); 138 139 sub_writer.Store32<0>(sender_next_tsn_.has_value() ? **sender_next_tsn_ 140 : 0); 141 sub_writer.Store32<4>(receiver_next_tsn_.has_value() ? **receiver_next_tsn_ 142 : 0); 143 } 144 } 145 ToString() const146std::string ReconfigurationResponseParameter::ToString() const { 147 rtc::StringBuilder sb; 148 sb << "Re-configuration Response, resp_seq_nbr=" 149 << *response_sequence_number(); 150 return sb.Release(); 151 } 152 } // namespace dcsctp 153