mediasoup 3.21.0 → 3.21.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +1882 -0
  2. package/node/lib/test/test-Consumer.js +111 -0
  3. package/node/lib/test/test-Producer.js +54 -0
  4. package/npm-scripts.mjs +0 -5
  5. package/package.json +9 -8
  6. package/worker/fuzzer/src/RTC/SCTP/association/FuzzerStateCookie.cpp +4 -6
  7. package/worker/include/RTC/NEW_RTCP/packet/ByePacket.hpp +165 -0
  8. package/worker/include/RTC/NEW_RTCP/packet/CompoundPacket.hpp +183 -0
  9. package/worker/include/RTC/NEW_RTCP/packet/Packet.hpp +354 -0
  10. package/worker/include/RTC/NEW_RTCP/packet/TODO_NEW_RTCP.md +17 -0
  11. package/worker/include/RTC/RTP/Codecs/Tools.hpp +2 -0
  12. package/worker/include/RTC/Router.hpp +4 -4
  13. package/worker/include/RTC/SCTP/association/Capabilities.hpp +73 -0
  14. package/worker/include/RTC/SCTP/association/NegotiatedCapabilities.hpp +7 -9
  15. package/worker/include/RTC/SCTP/association/StateCookie.hpp +38 -28
  16. package/worker/include/RTC/SCTP/packet/Chunk.hpp +11 -7
  17. package/worker/include/RTC/SCTP/packet/ErrorCause.hpp +11 -4
  18. package/worker/include/RTC/SCTP/packet/Packet.hpp +1 -1
  19. package/worker/include/RTC/SCTP/packet/Parameter.hpp +11 -4
  20. package/worker/include/RTC/SCTP/packet/TLV.hpp +2 -2
  21. package/worker/include/RTC/SCTP/packet/parameters/StateCookieParameter.hpp +2 -2
  22. package/worker/include/RTC/Transport.hpp +10 -10
  23. package/worker/include/Worker.hpp +4 -4
  24. package/worker/meson.build +7 -0
  25. package/worker/scripts/clang-scripts.mjs +54 -0
  26. package/worker/src/RTC/Consumer.cpp +22 -4
  27. package/worker/src/RTC/NEW_RTCP/packet/ByePacket.cpp +266 -0
  28. package/worker/src/RTC/NEW_RTCP/packet/CompoundPacket.cpp +219 -0
  29. package/worker/src/RTC/NEW_RTCP/packet/Packet.cpp +222 -0
  30. package/worker/src/RTC/RTP/Codecs/H264.cpp +3 -0
  31. package/worker/src/RTC/RTP/Codecs/VP8.cpp +3 -0
  32. package/worker/src/RTC/Router.cpp +14 -14
  33. package/worker/src/RTC/SCTP/association/Association.cpp +23 -11
  34. package/worker/src/RTC/SCTP/association/Capabilities.cpp +87 -0
  35. package/worker/src/RTC/SCTP/association/NegotiatedCapabilities.cpp +20 -40
  36. package/worker/src/RTC/SCTP/association/StateCookie.cpp +54 -32
  37. package/worker/src/RTC/SCTP/packet/Chunk.cpp +18 -18
  38. package/worker/src/RTC/SCTP/packet/ErrorCause.cpp +18 -18
  39. package/worker/src/RTC/SCTP/packet/Packet.cpp +2 -0
  40. package/worker/src/RTC/SCTP/packet/Parameter.cpp +18 -18
  41. package/worker/src/RTC/SCTP/packet/TLV.cpp +27 -25
  42. package/worker/src/RTC/SCTP/packet/parameters/StateCookieParameter.cpp +2 -2
  43. package/worker/src/RTC/SvcProducerStreamManager.cpp +4 -1
  44. package/worker/src/RTC/Transport.cpp +42 -30
  45. package/worker/src/Worker.cpp +10 -10
  46. package/worker/test/include/RTC/ICE/iceCommon.hpp +1 -1
  47. package/worker/test/include/RTC/RTCP/rtcpCommon.hpp +58 -0
  48. package/worker/test/include/RTC/RTP/rtpCommon.hpp +1 -1
  49. package/worker/test/src/RTC/NEW_RTCP/packet/TestByePacket.cpp +302 -0
  50. package/worker/test/src/RTC/NEW_RTCP/rtcpCommon.cpp +29 -0
  51. package/worker/test/src/RTC/RTP/TestPacket.cpp +17 -15
  52. package/worker/test/src/RTC/SCTP/association/TestAssociation.cpp +3 -3
  53. package/worker/test/src/RTC/SCTP/association/TestCapabilities.cpp +99 -0
  54. package/worker/test/src/RTC/SCTP/association/TestNegotiatedCapabilities.cpp +14 -16
  55. package/worker/test/src/RTC/SCTP/association/TestStateCookie.cpp +198 -102
  56. package/worker/test/src/RTC/SCTP/packet/parameters/TestStateCookieParameter.cpp +11 -10
@@ -0,0 +1,354 @@
1
+ #ifndef MS_RTC_NEW_RTCP_PACKET_HPP
2
+ #define MS_RTC_NEW_RTCP_PACKET_HPP
3
+
4
+ #include "common.hpp"
5
+ #include "RTC/Serializable.hpp"
6
+ #include "Utils.hpp"
7
+ #include <ankerl/unordered_dense.h>
8
+ #include <cstdint>
9
+ #include <string>
10
+
11
+ namespace RTC
12
+ {
13
+ namespace NEW_RTCP
14
+ {
15
+ /**
16
+ * RTCP Packet.
17
+ *
18
+ * @see RFC 3550.
19
+ *
20
+ * @remarks
21
+ * - This class represents a single RTCP packet and not a compound packet.
22
+ */
23
+ class Packet : public Serializable
24
+ {
25
+ // We need that CompoundPacket calls protected and private methods in this
26
+ // class.
27
+ friend class CompoundPacket;
28
+
29
+ public:
30
+ /**
31
+ * RTCP Packet Type.
32
+ */
33
+ enum class PacketType : uint8_t
34
+ {
35
+ /**
36
+ * Extended Jitter Report.
37
+ */
38
+ IJ = 195,
39
+ /**
40
+ * RTCP Sender Report.
41
+ */
42
+ SR = 200,
43
+ /**
44
+ * RTCP Receiver Report.
45
+ */
46
+ RR = 201,
47
+ /**
48
+ * RTCP Sender Report.
49
+ */
50
+ SDES = 202,
51
+ /**
52
+ * RTCP BYE.
53
+ */
54
+ BYE = 203,
55
+ /**
56
+ * RTCP APP.
57
+ */
58
+ APP = 204,
59
+ /**
60
+ * RTCP Transport Layer Feedback.
61
+ */
62
+ RTPFB = 205,
63
+ /**
64
+ * RTCP Payload Specific Feedback.
65
+ */
66
+ PSFB = 206,
67
+ /**
68
+ * RTCP Extended Report.
69
+ */
70
+ XR = 207,
71
+ };
72
+
73
+ /**
74
+ * RTCP Packet (RTCP Common Header + Value).
75
+ *
76
+ * @see RFC 3550.
77
+ *
78
+ * 0 1 2 3
79
+ * 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
80
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
81
+ * |V=2|P| Count | PT | Length |
82
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
83
+ * \ \
84
+ * / Value /
85
+ * \ \
86
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
87
+ *
88
+ * - Version (2 bits): RTP/RTCP version. Always 2.
89
+ * - Padding (1 bit): If set, the packet contains padding bytes at the
90
+ * end that are not part of the value. The last padding byte indicates
91
+ * how many padding bytes must be ignored, including itself (it will be
92
+ * a multiple of four).
93
+ * - Count (5 bits): Field whose meaning depends on the packet type
94
+ * (PT). RFC 3550 does not assign it a single name because it varies
95
+ * per packet: in Sender/Receiver Report it is the reception report
96
+ * block count (RC), in SDES and BYE it is the source count (SC), and
97
+ * in APP it acts as an application-defined subtype. It is treated
98
+ * generically as a 5-bit value specific to each packet type.
99
+ * - Packet type (8 bits): Identifies the RTCP packet type. Common
100
+ * values: 200 (SR), 201 (RR), 202 (SDES), 203 (BYE), 204 (APP).
101
+ * - Length (16 bits): Length of the RTCP packet in 32-bit words minus
102
+ * one, including the Common Header and any padding. Therefore the
103
+ * total size in bytes is (Length + 1) * 4.
104
+ * - Value (variable length): Packet content, whose format depends on
105
+ * the packet type (PT).
106
+ *
107
+ * @remarks
108
+ * - This struct is guaranteed to be aligned to 4 bytes.
109
+ * - The padding mechanism is not implemented since it's only used when
110
+ * encrypting the compound packet by following the section 9.1 of RFC
111
+ * 3550 which absolutely nobody does (SRTCP is used instead). So
112
+ * packets with Padding bit set to 1 are considered invalid and
113
+ * rejected.
114
+ */
115
+ struct CommonHeader
116
+ {
117
+ #if defined(MS_LITTLE_ENDIAN)
118
+ uint8_t count : 5;
119
+ uint8_t padding : 1;
120
+ uint8_t version : 2;
121
+ #elif defined(MS_BIG_ENDIAN)
122
+ uint8_t version : 2;
123
+ uint8_t padding : 1;
124
+ uint8_t count : 5;
125
+ #endif
126
+ PacketType packetType;
127
+ uint16_t length;
128
+ };
129
+
130
+ public:
131
+ /**
132
+ * Length (in bytes) of the RTCP Common Header.
133
+ */
134
+ static constexpr size_t CommonHeaderLength{ 4 };
135
+
136
+ /**
137
+ * Whether given buffer could be a valid RTCP packet.
138
+ */
139
+ static bool IsRtcp(const uint8_t* buffer, size_t bufferLength);
140
+
141
+ static const std::string& PacketTypeToString(PacketType packetType);
142
+
143
+ protected:
144
+ /**
145
+ * Whether given buffer could be a a valid RTCP packet.
146
+ *
147
+ * @param buffer
148
+ * @param bufferLength - Can be greater than real packet length.
149
+ * @param packetType - If given buffer is a valid packet then `packetType`
150
+ * is rewritten to parsed PacketType.
151
+ * @param packetLength - If given buffer is a valid packet then
152
+ * `packetLength` is rewritten to the computed length of the packet.
153
+ *
154
+ * @remarks
155
+ * - Packets with Padding bit set to 1 are not supported (see note above)
156
+ * and hence this function returns false if it's set.
157
+ */
158
+ static bool IsPacket(
159
+ const uint8_t* buffer, size_t bufferLength, PacketType& packetType, size_t& packetLength);
160
+
161
+ private:
162
+ static const ankerl::unordered_dense::map<PacketType, std::string> PacketType2String;
163
+
164
+ protected:
165
+ /**
166
+ * Constructor is protected because we only want to create packets
167
+ * instances via Parse() and Factory() in subclasses.
168
+ */
169
+ Packet(uint8_t* buffer, size_t bufferLength);
170
+
171
+ public:
172
+ ~Packet() override;
173
+
174
+ /**
175
+ * Must be overridden by each subclass.
176
+ */
177
+ void Dump(int indentation = 0) const override = 0;
178
+
179
+ /**
180
+ * Must be overridden by each subclass.
181
+ */
182
+ Packet* Clone(uint8_t* buffer, size_t bufferLength) const override = 0;
183
+
184
+ uint8_t GetVersion() const
185
+ {
186
+ return GetCommonHeaderPointer()->version;
187
+ }
188
+
189
+ PacketType GetType() const
190
+ {
191
+ return GetCommonHeaderPointer()->packetType;
192
+ }
193
+
194
+ /**
195
+ * False by default. UnknownPacket class overrides this method to return
196
+ * true instead.
197
+ */
198
+ virtual bool HasUnknownType() const
199
+ {
200
+ return false;
201
+ }
202
+
203
+ /**
204
+ * Whether the Padding bit is set to 1.
205
+ *
206
+ * @remarks
207
+ * - The padding mechanism is not implemented since it's only used when
208
+ * encrypting the compound packet by following the section 9.1 of RFC
209
+ * 3550 which absolutely nobody does (SRTCP is used instead). So
210
+ * packets with Padding bit set to 1 are considered invalid and
211
+ * rejected.
212
+ */
213
+ bool HasPadding() const
214
+ {
215
+ return GetCommonHeaderPointer()->padding;
216
+ }
217
+
218
+ protected:
219
+ /**
220
+ * Subclasses must invoke this method within their Dump() method.
221
+ */
222
+ void DumpCommon(int indentation) const;
223
+
224
+ virtual void SoftSerialize(const uint8_t* buffer) final;
225
+
226
+ /**
227
+ * Can be overridden by each subclass.
228
+ */
229
+ virtual Packet* SoftClone(const uint8_t* buffer) const = 0;
230
+
231
+ virtual void SoftCloneInto(Packet* packet) const final;
232
+
233
+ virtual void InitializeHeader(PacketType packetType, uint16_t length) final;
234
+
235
+ virtual uint8_t GetCount() const final
236
+ {
237
+ return GetCommonHeaderPointer()->count;
238
+ }
239
+
240
+ virtual void SetCount(uint8_t count) final
241
+ {
242
+ GetCommonHeaderPointer()->count = count;
243
+ }
244
+
245
+ /**
246
+ * Value of the Length field, which is the length of the RTCP packet in
247
+ * 32-bit words minus one, including the Common Header and any padding.
248
+ * Therefore the total size in bytes is (Length + 1) * 4.
249
+ */
250
+ virtual uint16_t GetLengthField() const final
251
+ {
252
+ return Utils::Byte::Get2Bytes(GetBuffer(), 2);
253
+ }
254
+
255
+ /**
256
+ * Computed value (in bytes) of the Length field.
257
+ */
258
+ virtual size_t GetLengthFieldComputed() const final
259
+ {
260
+ return (static_cast<size_t>(GetLengthField()) + 1) * 4;
261
+ }
262
+
263
+ /**
264
+ * Set the Length field given the total packet length in bytes. It
265
+ * encodes it as 32-bit words minus one as required by the RTCP Length
266
+ * field.
267
+ *
268
+ * @throw MediaSoupTypeError - If given `length` is higher than the maximum
269
+ * representable packet length (262144 bytes).
270
+ */
271
+ virtual void SetLengthField(size_t length) final;
272
+
273
+ /**
274
+ * A pointer to the position in the buffer where the variable-length value
275
+ * (if any) starts or should start.
276
+ */
277
+ virtual uint8_t* GetVariableLengthValuePointer() const final
278
+ {
279
+ return const_cast<uint8_t*>(GetBuffer()) + Packet::CommonHeaderLength;
280
+ }
281
+
282
+ /**
283
+ * Whether this packet contains a variable-length value.
284
+ *
285
+ * @see GetVariableLengthValue()
286
+ */
287
+ virtual bool HasVariableLengthValue() const final
288
+ {
289
+ return GetLengthFieldComputed() > Packet::CommonHeaderLength;
290
+ }
291
+
292
+ /**
293
+ * Variable-length value of this packet.
294
+ */
295
+ virtual const uint8_t* GetVariableLengthValue() const final
296
+ {
297
+ if (!HasVariableLengthValue())
298
+ {
299
+ return nullptr;
300
+ }
301
+
302
+ return GetVariableLengthValuePointer();
303
+ }
304
+
305
+ /**
306
+ * Set the variable-length value. It copies the given value into the
307
+ * the variable-length value of the packet and updates both the length of
308
+ * the Serializable and the length field.
309
+ *
310
+ * @throw MediaSoupTypeError - If given `valueLength` is higher than
311
+ * available length.
312
+ *
313
+ * @see GetVariableLengthValue()
314
+ */
315
+ virtual void SetVariableLengthValue(const uint8_t* value, size_t valueLength) final;
316
+
317
+ /**
318
+ * The length of the variable-length value.
319
+ */
320
+ virtual size_t GetVariableLengthValueLength() const final
321
+ {
322
+ if (!HasVariableLengthValue())
323
+ {
324
+ return 0u;
325
+ }
326
+
327
+ return GetLengthFieldComputed() - Packet::CommonHeaderLength;
328
+ }
329
+
330
+ /**
331
+ * Set the length of the variable-length value. It doesn't copy any value
332
+ * into the variable-length value. This method is used in packets that
333
+ * have variable-length value but it doesn't consist on a buffer + length,
334
+ * but instead is an structure with fields (with variable length).
335
+ *
336
+ * @see GetVariableLengthValue()
337
+ */
338
+ virtual void SetVariableLengthValueLength(size_t valueLength) final;
339
+
340
+ private:
341
+ /**
342
+ * @remarks
343
+ * - Returns CommonHeader* instead of const CommonHeader* since we may want
344
+ * to modify its fields.
345
+ */
346
+ CommonHeader* GetCommonHeaderPointer() const
347
+ {
348
+ return reinterpret_cast<CommonHeader*>(const_cast<uint8_t*>(GetBuffer()));
349
+ }
350
+ };
351
+ } // namespace NEW_RTCP
352
+ } // namespace RTC
353
+
354
+ #endif
@@ -0,0 +1,17 @@
1
+ # TODO NEW RTCP
2
+
3
+ - Remove `NEW_` prefix in folders.
4
+
5
+ - Remove `NEW_` prefix in C++ `NEW_RTCP` namespace.
6
+
7
+ - Remove `NEW_` prefix in `#ifndef` in `.hpp` files.
8
+
9
+ - We are not implementing `NeedsConsolidation()` in `Packet` class (only in `CompoundPacket` class). For now it's ok. Let's see.
10
+
11
+ - `Packet`: Check if we need all those `Get/SetVariableLengthXxxxxx()` methods.
12
+
13
+ - All the `TODO` comments.
14
+
15
+ - Tests for `Packet` and `CompoundPacket`.
16
+
17
+ - Fuzzer for `Packet` and `CompoundPacket`.
@@ -159,7 +159,9 @@ namespace RTC
159
159
  {
160
160
  switch (mimeType.subtype)
161
161
  {
162
+ case RTC::RtpCodecMimeType::Subtype::VP8:
162
163
  case RTC::RtpCodecMimeType::Subtype::VP9:
164
+ case RTC::RtpCodecMimeType::Subtype::H264:
163
165
  case RTC::RtpCodecMimeType::Subtype::AV1:
164
166
  {
165
167
  return true;
@@ -49,11 +49,11 @@ namespace RTC
49
49
 
50
50
  private:
51
51
  RTC::Transport* AssertAndGetTransportById(
52
- const std::string& transportId, const std::string& message) const;
52
+ const std::string& transportId, const std::string& method) const;
53
53
  RTC::RtpObserver* AssertAndGetRtpObserverById(
54
- const std::string& rtpObserverId, const std::string& message) const;
55
- void CheckNoTransport(const std::string& transportId, const std::string& message) const;
56
- void CheckNoRtpObserver(const std::string& rtpObserverId, const std::string& message) const;
54
+ const std::string& rtpObserverId, const std::string& method) const;
55
+ void CheckNoTransport(const std::string& transportId, const std::string& method) const;
56
+ void CheckNoRtpObserver(const std::string& rtpObserverId, const std::string& method) const;
57
57
 
58
58
  /* Pure virtual methods inherited from RTC::Transport::Listener. */
59
59
  public:
@@ -0,0 +1,73 @@
1
+ #ifndef MS_RTC_SCTP_CAPABILITIES_HPP
2
+ #define MS_RTC_SCTP_CAPABILITIES_HPP
3
+
4
+ #include "common.hpp"
5
+ #include "RTC/SCTP/packet/chunks/AnyInitChunk.hpp"
6
+ #include "RTC/SCTP/packet/parameters/ZeroChecksumAcceptableParameter.hpp"
7
+
8
+ namespace RTC
9
+ {
10
+ namespace SCTP
11
+ {
12
+ /**
13
+ * Those are the raw SCTP capabilities announced by an endpoint in its INIT
14
+ * or INIT-ACK chunk, before any negotiation against local options takes
15
+ * place.
16
+ */
17
+ struct Capabilities
18
+ {
19
+ /**
20
+ * Create a Capabilities struct holding the capabilities announced by
21
+ * the remote endpoint. No local option is applied here.
22
+ *
23
+ * @remarks
24
+ * - Given `remoteChunk` must be an INIT or an INIT-ACK chunk.
25
+ */
26
+ static Capabilities Factory(const AnyInitChunk* remoteChunk);
27
+
28
+ /**
29
+ * Maximum number of outbound streams (OS).
30
+ */
31
+ uint16_t maxOutboundStreams{ 0 };
32
+
33
+ /**
34
+ * Maximum number of inbound streams (MIS).
35
+ */
36
+ uint16_t maxInboundStreams{ 0 };
37
+
38
+ /**
39
+ * Partial Reliability Extension.
40
+ *
41
+ * @see RFC 3758.
42
+ */
43
+ bool partialReliability{ false };
44
+
45
+ /**
46
+ * Stream Schedulers and User Message Interleaving (I-DATA chunks).
47
+ *
48
+ * @see RFC 8260.
49
+ */
50
+ bool messageInterleaving{ false };
51
+
52
+ /**
53
+ * Stream Re-Configuration.
54
+ *
55
+ * @see RFC 6525.
56
+ */
57
+ bool reConfig{ false };
58
+
59
+ /**
60
+ * Alternate Error Detection Method for Zero Checksum.
61
+ *
62
+ * @see RFC 9653.
63
+ */
64
+ ZeroChecksumAcceptableParameter::AlternateErrorDetectionMethod zeroChecksumAlternateErrorDetectionMethod{
65
+ ZeroChecksumAcceptableParameter::AlternateErrorDetectionMethod::NONE
66
+ };
67
+
68
+ void Dump(int indentation = 0) const;
69
+ };
70
+ } // namespace SCTP
71
+ } // namespace RTC
72
+
73
+ #endif
@@ -2,7 +2,7 @@
2
2
  #define MS_RTC_SCTP_NEGOTIATED_CAPABILITIES_HPP
3
3
 
4
4
  #include "common.hpp"
5
- #include "RTC/SCTP/packet/chunks/AnyInitChunk.hpp"
5
+ #include "RTC/SCTP/association/Capabilities.hpp"
6
6
  #include "RTC/SCTP/public/SctpOptions.hpp"
7
7
 
8
8
  namespace RTC
@@ -17,24 +17,22 @@ namespace RTC
17
17
  struct NegotiatedCapabilities
18
18
  {
19
19
  /**
20
- * Create a NegotiatedCapabilities struct. Intended to be used during
21
- * the SCTP association handshake flow.
22
- *
23
- * @remarks
24
- * - Given `remoteChunk` must be an INIT or an INIT-ACK chunk.
20
+ * Create a NegotiatedCapabilities struct by negotiating the capabilities
21
+ * announced by the remote endpoint against our local options. Intended
22
+ * to be used during the SCTP association handshake flow.
25
23
  */
26
24
  static NegotiatedCapabilities Factory(
27
- const SctpOptions& sctpOptions, const AnyInitChunk* remoteChunk);
25
+ const SctpOptions& sctpOptions, const Capabilities& remoteCapabilities);
28
26
 
29
27
  /**
30
28
  * Negotiated maximum number of outbound streams (OS).
31
29
  */
32
- uint16_t negotiatedMaxOutboundStreams{ 0 };
30
+ uint16_t maxOutboundStreams{ 0 };
33
31
 
34
32
  /**
35
33
  * Negotiated maximum number of inbound streams (MIS).
36
34
  */
37
- uint16_t negotiatedMaxInboundStreams{ 0 };
35
+ uint16_t maxInboundStreams{ 0 };
38
36
 
39
37
  /**
40
38
  * Partial Reliability Extension.
@@ -2,7 +2,7 @@
2
2
  #define MS_RTC_SCTP_STATE_COOKIE_HPP
3
3
 
4
4
  #include "common.hpp"
5
- #include "RTC/SCTP/association/NegotiatedCapabilities.hpp"
5
+ #include "RTC/SCTP/association/Capabilities.hpp"
6
6
  #include "RTC/SCTP/public/SctpTypes.hpp"
7
7
  #include "RTC/Serializable.hpp"
8
8
  #include "Utils.hpp"
@@ -38,30 +38,41 @@ namespace RTC
38
38
  * | |
39
39
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40
40
  * \ \
41
- * / Negotiated Capabilities /
41
+ * / Remote Capabilities /
42
42
  * \ \
43
43
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44
44
  *
45
- * Negotiated Capabilities are serialized as follows:
45
+ * The Remote Capabilities are the raw capabilities announced by the remote
46
+ * endpoint in its INIT or INIT-ACK chunk (before being negotiated against
47
+ * our local options). Storing the raw remote capabilities (instead of the
48
+ * already negotiated ones) limits the effect of a tampered/forged cookie:
49
+ * when the COOKIE-ECHO is received they are re-negotiated against our local
50
+ * options, so an attacker can never enable an extension we didn't signal
51
+ * nor raise the stream limits above what we announced.
52
+ *
53
+ * Remote Capabilities are serialized as follows:
46
54
  *
47
55
  * 0 1 2 3
48
56
  * 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
49
57
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50
- * | (Reserved) | |D|C|B|A| Magic 2 |
58
+ * | (Reserved) | |C|B|A| Magic 2 |
59
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60
+ * | Zero Checksum Alternate Error Detection Method |
51
61
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52
62
  * | Max Outbound Streams | Max Inbound Streams |
53
63
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54
64
  *
55
65
  * - Flag A (partialReliability): Partial Reliability Extension.
56
66
  * - Flag B (messageInterleaving): Stream Schedulers and User Message
57
- * Interleaving (I-DATA).
58
- * - Flag C (reconfig): Stream Reconfiguration.
59
- * - Flag D (zeroChecksum): Zero Checksum.
67
+ * Interleaving (I-DATA).
68
+ * - Flag C (reConfig): Stream Reconfiguration.
69
+ * - Zero Checksum Alternate Error Detection Method: the method announced
70
+ * by the remote endpoint (0 means none).
60
71
  *
61
72
  * When State Cookie authentication is enabled (see
62
73
  * `SctpOptions::requireAuthenticatedCookie`), two extra fields are appended
63
- * after the Negotiated Capabilities so the receiver can verify that the
64
- * cookie was generated by itself and is not stale:
74
+ * after the Remote Capabilities so the receiver can verify that the cookie
75
+ * was generated by itself and is not stale:
65
76
  *
66
77
  * 0 1 2 3
67
78
  * 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
@@ -83,39 +94,37 @@ namespace RTC
83
94
  class StateCookie : public Serializable
84
95
  {
85
96
  private:
86
- struct NegotiatedCapabilitiesField
97
+ struct RemoteCapabilitiesField
87
98
  {
88
99
  uint8_t reserved;
89
100
  #if defined(MS_LITTLE_ENDIAN)
90
101
  uint8_t bitA : 1;
91
102
  uint8_t bitB : 1;
92
103
  uint8_t bitC : 1;
93
- uint8_t bitD : 1;
94
- uint8_t unusedBits : 4;
104
+ uint8_t unusedBits : 5;
95
105
  #elif defined(MS_BIG_ENDIAN)
96
- uint8_t unusedBits : 4;
97
- uint8_t bitD : 1;
106
+ uint8_t unusedBits : 5;
98
107
  uint8_t bitC : 1;
99
108
  uint8_t bitB : 1;
100
109
  uint8_t bitA : 1;
101
110
  #endif
102
111
  uint16_t magic2;
103
- uint16_t negotiatedMaxOutboundStreams;
104
- uint16_t negotiatedMaxInboundStreams;
112
+ uint32_t zeroChecksumAlternateErrorDetectionMethod;
113
+ uint16_t maxOutboundStreams;
114
+ uint16_t maxInboundStreams;
105
115
  };
106
116
 
107
117
  public:
108
118
  // Fixed length of our generated State Cookies when authentication is
109
119
  // disabled.
110
- static constexpr size_t StateCookieLength{ 44 };
111
- // Offset in the State Cookie where the Negotiated Capabilitied are
112
- // located.
113
- static constexpr size_t NegotiatedCapabilitiesOffset{ 36 };
120
+ static constexpr size_t StateCookieLength{ 48 };
121
+ // Offset in the State Cookie where the Remote Capabilities are located.
122
+ static constexpr size_t RemoteCapabilitiesOffset{ 36 };
114
123
  // Magic value we prefix the State Cookie with. Note that it is
115
124
  // "msworker" in ASCII bytes.
116
125
  static constexpr uint64_t Magic1{ 0x6D73776F726B6572 };
117
126
  static constexpr size_t Magic1Length{ 8 };
118
- // Magic value used within the Negotiated Capabilities block.
127
+ // Magic value used within the Remote Capabilities block.
119
128
  static constexpr uint16_t Magic2{ 0xAD81 };
120
129
  // Offset of the creation timestamp present in authenticated State
121
130
  // Cookies.
@@ -165,7 +174,7 @@ namespace RTC
165
174
  uint32_t remoteInitialTsn,
166
175
  uint32_t remoteAdvertisedReceiverWindowCredit,
167
176
  uint64_t tieTag,
168
- const NegotiatedCapabilities& negotiatedCapabilities,
177
+ const Capabilities& remoteCapabilities,
169
178
  uint64_t creationTimestampMs = 0,
170
179
  const uint8_t* macKey = nullptr,
171
180
  size_t macKeyLength = 0);
@@ -187,7 +196,7 @@ namespace RTC
187
196
  uint32_t remoteInitialTsn,
188
197
  uint32_t remoteAdvertisedReceiverWindowCredit,
189
198
  uint64_t tieTag,
190
- const NegotiatedCapabilities& negotiatedCapabilities,
199
+ const Capabilities& remoteCapabilities,
191
200
  uint64_t creationTimestampMs = 0,
192
201
  const uint8_t* macKey = nullptr,
193
202
  size_t macKeyLength = 0);
@@ -287,9 +296,10 @@ namespace RTC
287
296
  }
288
297
 
289
298
  /**
290
- * Negotiated association capabilities.
299
+ * Raw capabilities announced by the remote endpoint (before being
300
+ * negotiated against our local options).
291
301
  */
292
- NegotiatedCapabilities GetNegotiatedCapabilities() const;
302
+ Capabilities GetRemoteCapabilities() const;
293
303
 
294
304
  /**
295
305
  * Whether this is an authenticated StateCookie (i.e. it carries a
@@ -312,10 +322,10 @@ namespace RTC
312
322
  }
313
323
 
314
324
  private:
315
- NegotiatedCapabilitiesField* GetNegotiatedCapabilitiesField() const
325
+ RemoteCapabilitiesField* GetRemoteCapabilitiesField() const
316
326
  {
317
- return reinterpret_cast<NegotiatedCapabilitiesField*>(
318
- const_cast<uint8_t*>(GetBuffer()) + StateCookie::NegotiatedCapabilitiesOffset);
327
+ return reinterpret_cast<RemoteCapabilitiesField*>(
328
+ const_cast<uint8_t*>(GetBuffer()) + StateCookie::RemoteCapabilitiesOffset);
319
329
  }
320
330
  };
321
331
  } // namespace SCTP