blob: 3677a9a0bb7fef51308796be9878c3876ee3694a [file] [log] [blame]
wu@webrtc.org1d1ffc92013-10-16 18:12:021/*
kjellanderb24317b2016-02-10 15:54:432 * Copyright 2013 The WebRTC project authors. All Rights Reserved.
wu@webrtc.org1d1ffc92013-10-16 18:12:023 *
kjellanderb24317b2016-02-10 15:54:434 * 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.
wu@webrtc.org1d1ffc92013-10-16 18:12:029 */
10
Steve Anton10542f22019-01-11 17:11:0011#include "pc/sctp_utils.h"
wu@webrtc.org1d1ffc92013-10-16 18:12:0212
Yves Gerey3e707812018-11-28 15:47:4913#include <stddef.h>
Harald Alvestrandc24a2182022-02-23 13:44:5914
15#include <cstdint>
Yves Gerey3e707812018-11-28 15:47:4916
Harald Alvestrand5761e7b2021-01-29 14:45:0817#include "absl/types/optional.h"
Harald Alvestrandfd5ae7f2020-05-16 06:37:4918#include "api/priority.h"
Tommi492296c2023-03-12 15:59:2519#include "media/sctp/sctp_transport_internal.h"
Steve Anton10542f22019-01-11 17:11:0020#include "rtc_base/byte_buffer.h"
21#include "rtc_base/copy_on_write_buffer.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3122#include "rtc_base/logging.h"
wu@webrtc.org1d1ffc92013-10-16 18:12:0223
henrika@webrtc.orgaebb1ad2014-01-14 10:00:5824namespace webrtc {
wu@webrtc.org1d1ffc92013-10-16 18:12:0225
26// Format defined at
henrika@webrtc.orgaebb1ad2014-01-14 10:00:5827// http://tools.ietf.org/html/draft-ietf-rtcweb-data-protocol-01#section
wu@webrtc.org1d1ffc92013-10-16 18:12:0228
Peter Boström0c4e06b2015-10-07 10:23:2129static const uint8_t DATA_CHANNEL_OPEN_MESSAGE_TYPE = 0x03;
30static const uint8_t DATA_CHANNEL_OPEN_ACK_MESSAGE_TYPE = 0x02;
wu@webrtc.org1d1ffc92013-10-16 18:12:0231
32enum DataChannelOpenMessageChannelType {
33 DCOMCT_ORDERED_RELIABLE = 0x00,
34 DCOMCT_ORDERED_PARTIAL_RTXS = 0x01,
35 DCOMCT_ORDERED_PARTIAL_TIME = 0x02,
36 DCOMCT_UNORDERED_RELIABLE = 0x80,
37 DCOMCT_UNORDERED_PARTIAL_RTXS = 0x81,
38 DCOMCT_UNORDERED_PARTIAL_TIME = 0x82,
39};
40
Harald Alvestrandfd5ae7f2020-05-16 06:37:4941// Values of priority in the DC open protocol message.
42// These are compared against an integer, so are enum, not enum class.
43enum DataChannelPriority {
44 DCO_PRIORITY_VERY_LOW = 128,
45 DCO_PRIORITY_LOW = 256,
46 DCO_PRIORITY_MEDIUM = 512,
47 DCO_PRIORITY_HIGH = 1024,
48};
49
Tommi492296c2023-03-12 15:59:2550StreamId::StreamId() : id_(absl::nullopt) {
51 thread_checker_.Detach();
52}
53
54StreamId::StreamId(int id)
55 : id_(id >= cricket::kMinSctpSid && id <= cricket::kSpecMaxSctpSid
56 ? absl::optional<uint16_t>(static_cast<uint16_t>(id))
57 : absl::nullopt) {
58 thread_checker_.Detach();
59}
60
61StreamId::StreamId(const StreamId& sid) : id_(sid.id_) {}
62
63bool StreamId::HasValue() const {
64 RTC_DCHECK_RUN_ON(&thread_checker_);
65 return id_.has_value();
66}
67
68int StreamId::stream_id_int() const {
69 RTC_DCHECK_RUN_ON(&thread_checker_);
70 return id_.has_value() ? static_cast<int>(id_.value().value()) : -1;
71}
72
73void StreamId::reset() {
74 RTC_DCHECK_RUN_ON(&thread_checker_);
75 id_ = absl::nullopt;
76}
77
78StreamId& StreamId::operator=(const StreamId& sid) {
79 RTC_DCHECK_RUN_ON(&thread_checker_);
80 RTC_DCHECK_RUN_ON(&sid.thread_checker_);
81 id_ = sid.id_;
82 return *this;
83}
84
85bool StreamId::operator==(const StreamId& sid) const {
86 RTC_DCHECK_RUN_ON(&thread_checker_);
87 RTC_DCHECK_RUN_ON(&sid.thread_checker_);
88 return id_ == sid.id_;
89}
90
91bool StreamId::operator<(const StreamId& sid) const {
92 RTC_DCHECK_RUN_ON(&thread_checker_);
93 RTC_DCHECK_RUN_ON(&sid.thread_checker_);
94 return id_ < sid.id_;
95}
96
jbaucheec21bd2016-03-20 13:15:4397bool IsOpenMessage(const rtc::CopyOnWriteBuffer& payload) {
deadbeefab9b2d12015-10-14 18:33:1198 // Format defined at
Tommi5bbfb002023-03-04 15:47:5399 // https://www.rfc-editor.org/rfc/rfc8832#section-5.1
jbaucheec21bd2016-03-20 13:15:43100 if (payload.size() < 1) {
Tommi5bbfb002023-03-04 15:47:53101 RTC_DLOG(LS_WARNING) << "Could not read OPEN message type.";
deadbeefab9b2d12015-10-14 18:33:11102 return false;
103 }
jbaucheec21bd2016-03-20 13:15:43104
105 uint8_t message_type = payload[0];
deadbeefab9b2d12015-10-14 18:33:11106 return message_type == DATA_CHANNEL_OPEN_MESSAGE_TYPE;
107}
108
jbaucheec21bd2016-03-20 13:15:43109bool ParseDataChannelOpenMessage(const rtc::CopyOnWriteBuffer& payload,
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58110 std::string* label,
111 DataChannelInit* config) {
wu@webrtc.org1d1ffc92013-10-16 18:12:02112 // Format defined at
113 // http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04
114
jbauchf1f87202016-03-30 13:43:37115 rtc::ByteBufferReader buffer(payload.data<char>(), payload.size());
Peter Boström0c4e06b2015-10-07 10:23:21116 uint8_t message_type;
wu@webrtc.org1d1ffc92013-10-16 18:12:02117 if (!buffer.ReadUInt8(&message_type)) {
Mirko Bonadei675513b2017-11-09 10:09:25118 RTC_LOG(LS_WARNING) << "Could not read OPEN message type.";
wu@webrtc.org1d1ffc92013-10-16 18:12:02119 return false;
120 }
121 if (message_type != DATA_CHANNEL_OPEN_MESSAGE_TYPE) {
Mirko Bonadei675513b2017-11-09 10:09:25122 RTC_LOG(LS_WARNING) << "Data Channel OPEN message of unexpected type: "
123 << message_type;
wu@webrtc.org1d1ffc92013-10-16 18:12:02124 return false;
125 }
126
Peter Boström0c4e06b2015-10-07 10:23:21127 uint8_t channel_type;
wu@webrtc.org1d1ffc92013-10-16 18:12:02128 if (!buffer.ReadUInt8(&channel_type)) {
Mirko Bonadei675513b2017-11-09 10:09:25129 RTC_LOG(LS_WARNING) << "Could not read OPEN message channel type.";
wu@webrtc.org1d1ffc92013-10-16 18:12:02130 return false;
131 }
wu@webrtc.org97077a32013-10-25 21:18:33132
Peter Boström0c4e06b2015-10-07 10:23:21133 uint16_t priority;
wu@webrtc.org1d1ffc92013-10-16 18:12:02134 if (!buffer.ReadUInt16(&priority)) {
Mirko Bonadei675513b2017-11-09 10:09:25135 RTC_LOG(LS_WARNING)
136 << "Could not read OPEN message reliabilility prioirty.";
wu@webrtc.org1d1ffc92013-10-16 18:12:02137 return false;
138 }
Harald Alvestrandfd5ae7f2020-05-16 06:37:49139 // Parse priority as defined in
140 // https://w3c.github.io/webrtc-priority/#rtcdatachannel-processing-steps
141 if (priority <= DCO_PRIORITY_VERY_LOW) {
142 config->priority = Priority::kVeryLow;
143 } else if (priority <= DCO_PRIORITY_LOW) {
144 config->priority = Priority::kLow;
145 } else if (priority <= DCO_PRIORITY_MEDIUM) {
146 config->priority = Priority::kMedium;
147 } else {
148 config->priority = Priority::kHigh;
149 }
150
Peter Boström0c4e06b2015-10-07 10:23:21151 uint32_t reliability_param;
wu@webrtc.org97077a32013-10-25 21:18:33152 if (!buffer.ReadUInt32(&reliability_param)) {
Mirko Bonadei675513b2017-11-09 10:09:25153 RTC_LOG(LS_WARNING) << "Could not read OPEN message reliabilility param.";
wu@webrtc.org97077a32013-10-25 21:18:33154 return false;
155 }
Peter Boström0c4e06b2015-10-07 10:23:21156 uint16_t label_length;
wu@webrtc.org1d1ffc92013-10-16 18:12:02157 if (!buffer.ReadUInt16(&label_length)) {
Mirko Bonadei675513b2017-11-09 10:09:25158 RTC_LOG(LS_WARNING) << "Could not read OPEN message label length.";
wu@webrtc.org1d1ffc92013-10-16 18:12:02159 return false;
160 }
Peter Boström0c4e06b2015-10-07 10:23:21161 uint16_t protocol_length;
wu@webrtc.org1d1ffc92013-10-16 18:12:02162 if (!buffer.ReadUInt16(&protocol_length)) {
Mirko Bonadei675513b2017-11-09 10:09:25163 RTC_LOG(LS_WARNING) << "Could not read OPEN message protocol length.";
wu@webrtc.org1d1ffc92013-10-16 18:12:02164 return false;
165 }
Yves Gerey665174f2018-06-19 13:03:05166 if (!buffer.ReadString(label, (size_t)label_length)) {
Mirko Bonadei675513b2017-11-09 10:09:25167 RTC_LOG(LS_WARNING) << "Could not read OPEN message label";
wu@webrtc.org1d1ffc92013-10-16 18:12:02168 return false;
169 }
170 if (!buffer.ReadString(&config->protocol, protocol_length)) {
Mirko Bonadei675513b2017-11-09 10:09:25171 RTC_LOG(LS_WARNING) << "Could not read OPEN message protocol.";
wu@webrtc.org1d1ffc92013-10-16 18:12:02172 return false;
173 }
174
175 config->ordered = true;
176 switch (channel_type) {
177 case DCOMCT_UNORDERED_RELIABLE:
178 case DCOMCT_UNORDERED_PARTIAL_RTXS:
179 case DCOMCT_UNORDERED_PARTIAL_TIME:
180 config->ordered = false;
181 }
182
Harald Alvestrandf3736ed2019-04-08 11:09:30183 config->maxRetransmits = absl::nullopt;
184 config->maxRetransmitTime = absl::nullopt;
wu@webrtc.org1d1ffc92013-10-16 18:12:02185 switch (channel_type) {
186 case DCOMCT_ORDERED_PARTIAL_RTXS:
187 case DCOMCT_UNORDERED_PARTIAL_RTXS:
188 config->maxRetransmits = reliability_param;
wu@webrtc.org97077a32013-10-25 21:18:33189 break;
wu@webrtc.org1d1ffc92013-10-16 18:12:02190 case DCOMCT_ORDERED_PARTIAL_TIME:
191 case DCOMCT_UNORDERED_PARTIAL_TIME:
192 config->maxRetransmitTime = reliability_param;
wu@webrtc.org97077a32013-10-25 21:18:33193 break;
wu@webrtc.org1d1ffc92013-10-16 18:12:02194 }
wu@webrtc.org1d1ffc92013-10-16 18:12:02195 return true;
196}
197
jbaucheec21bd2016-03-20 13:15:43198bool ParseDataChannelOpenAckMessage(const rtc::CopyOnWriteBuffer& payload) {
199 if (payload.size() < 1) {
Mirko Bonadei675513b2017-11-09 10:09:25200 RTC_LOG(LS_WARNING) << "Could not read OPEN_ACK message type.";
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58201 return false;
202 }
jbaucheec21bd2016-03-20 13:15:43203
204 uint8_t message_type = payload[0];
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58205 if (message_type != DATA_CHANNEL_OPEN_ACK_MESSAGE_TYPE) {
Mirko Bonadei675513b2017-11-09 10:09:25206 RTC_LOG(LS_WARNING) << "Data Channel OPEN_ACK message of unexpected type: "
207 << message_type;
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58208 return false;
209 }
210 return true;
211}
212
213bool WriteDataChannelOpenMessage(const std::string& label,
214 const DataChannelInit& config,
jbaucheec21bd2016-03-20 13:15:43215 rtc::CopyOnWriteBuffer* payload) {
Tommi492296c2023-03-12 15:59:25216 return WriteDataChannelOpenMessage(label, config.protocol, config.priority,
217 config.ordered, config.maxRetransmits,
218 config.maxRetransmitTime, payload);
219}
220
221bool WriteDataChannelOpenMessage(const std::string& label,
222 const std::string& protocol,
223 absl::optional<Priority> opt_priority,
224 bool ordered,
225 absl::optional<int> max_retransmits,
226 absl::optional<int> max_retransmit_time,
227 rtc::CopyOnWriteBuffer* payload) {
wu@webrtc.org1d1ffc92013-10-16 18:12:02228 // Format defined at
Harald Alvestrandf3736ed2019-04-08 11:09:30229 // http://tools.ietf.org/html/draft-ietf-rtcweb-data-protocol-09#section-5.1
Peter Boström0c4e06b2015-10-07 10:23:21230 uint8_t channel_type = 0;
231 uint32_t reliability_param = 0;
232 uint16_t priority = 0;
Harald Alvestrandfd5ae7f2020-05-16 06:37:49233 // Set priority according to
234 // https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-12#section-6.4
Tommi492296c2023-03-12 15:59:25235 if (opt_priority) {
236 switch (*opt_priority) {
Harald Alvestrandfd5ae7f2020-05-16 06:37:49237 case Priority::kVeryLow:
238 priority = DCO_PRIORITY_VERY_LOW;
239 break;
240 case Priority::kLow:
241 priority = DCO_PRIORITY_LOW;
242 break;
243 case Priority::kMedium:
244 priority = DCO_PRIORITY_MEDIUM;
245 break;
246 case Priority::kHigh:
247 priority = DCO_PRIORITY_HIGH;
248 break;
249 }
250 }
Tommi492296c2023-03-12 15:59:25251 if (ordered) {
252 if (max_retransmits) {
wu@webrtc.org1d1ffc92013-10-16 18:12:02253 channel_type = DCOMCT_ORDERED_PARTIAL_RTXS;
Tommi492296c2023-03-12 15:59:25254 reliability_param = *max_retransmits;
255 } else if (max_retransmit_time) {
wu@webrtc.org1d1ffc92013-10-16 18:12:02256 channel_type = DCOMCT_ORDERED_PARTIAL_TIME;
Tommi492296c2023-03-12 15:59:25257 reliability_param = *max_retransmit_time;
wu@webrtc.org1d1ffc92013-10-16 18:12:02258 } else {
259 channel_type = DCOMCT_ORDERED_RELIABLE;
260 }
261 } else {
Tommi492296c2023-03-12 15:59:25262 if (max_retransmits) {
wu@webrtc.org1d1ffc92013-10-16 18:12:02263 channel_type = DCOMCT_UNORDERED_PARTIAL_RTXS;
Tommi492296c2023-03-12 15:59:25264 reliability_param = *max_retransmits;
265 } else if (max_retransmit_time) {
wu@webrtc.org1d1ffc92013-10-16 18:12:02266 channel_type = DCOMCT_UNORDERED_PARTIAL_TIME;
Tommi492296c2023-03-12 15:59:25267 reliability_param = *max_retransmit_time;
wu@webrtc.org1d1ffc92013-10-16 18:12:02268 } else {
269 channel_type = DCOMCT_UNORDERED_RELIABLE;
270 }
271 }
272
Tommi492296c2023-03-12 15:59:25273 rtc::ByteBufferWriter buffer(NULL, 20 + label.length() + protocol.length());
jbaucheec21bd2016-03-20 13:15:43274 // TODO(tommi): Add error handling and check resulting length.
wu@webrtc.org1d1ffc92013-10-16 18:12:02275 buffer.WriteUInt8(DATA_CHANNEL_OPEN_MESSAGE_TYPE);
276 buffer.WriteUInt8(channel_type);
wu@webrtc.org1d1ffc92013-10-16 18:12:02277 buffer.WriteUInt16(priority);
wu@webrtc.org97077a32013-10-25 21:18:33278 buffer.WriteUInt32(reliability_param);
Peter Boström0c4e06b2015-10-07 10:23:21279 buffer.WriteUInt16(static_cast<uint16_t>(label.length()));
Tommi492296c2023-03-12 15:59:25280 buffer.WriteUInt16(static_cast<uint16_t>(protocol.length()));
wu@webrtc.org1d1ffc92013-10-16 18:12:02281 buffer.WriteString(label);
Tommi492296c2023-03-12 15:59:25282 buffer.WriteString(protocol);
wu@webrtc.org1d1ffc92013-10-16 18:12:02283 payload->SetData(buffer.Data(), buffer.Length());
284 return true;
285}
286
jbaucheec21bd2016-03-20 13:15:43287void WriteDataChannelOpenAckMessage(rtc::CopyOnWriteBuffer* payload) {
288 uint8_t data = DATA_CHANNEL_OPEN_ACK_MESSAGE_TYPE;
289 payload->SetData(&data, sizeof(data));
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58290}
jbaucheec21bd2016-03-20 13:15:43291
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58292} // namespace webrtc