mediasoup 3.20.1 → 3.20.3
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.
- package/node/lib/DataConsumer.d.ts +2 -3
- package/node/lib/DataConsumer.d.ts.map +1 -1
- package/node/lib/DataConsumer.js +8 -6
- package/node/lib/DataConsumerTypes.d.ts +5 -4
- package/node/lib/DataConsumerTypes.d.ts.map +1 -1
- package/node/lib/fbs/data-consumer/send-response.d.ts +21 -0
- package/node/lib/fbs/data-consumer/send-response.d.ts.map +1 -0
- package/node/lib/fbs/data-consumer/send-response.js +91 -0
- package/node/lib/fbs/data-consumer.d.ts +1 -0
- package/node/lib/fbs/data-consumer.d.ts.map +1 -1
- package/node/lib/fbs/data-consumer.js +4 -1
- package/node/lib/fbs/response/body.d.ts +7 -5
- package/node/lib/fbs/response/body.d.ts.map +1 -1
- package/node/lib/fbs/response/body.js +7 -3
- package/node/lib/fbs/response/response.d.ts +3 -2
- package/node/lib/fbs/response/response.d.ts.map +1 -1
- package/node/lib/test/test-DataConsumer.js +6 -0
- package/node/lib/test/test-werift-sctp.js +7 -0
- package/npm-scripts.mjs +26 -0
- package/package.json +6 -5
- package/worker/Makefile +5 -1
- package/worker/fbs/dataConsumer.fbs +4 -0
- package/worker/fbs/response.fbs +1 -0
- package/worker/include/RTC/PortManager.hpp +91 -11
- package/worker/include/RTC/SCTP/association/HeartbeatHandler.hpp +3 -3
- package/worker/include/RTC/SCTP/association/StreamResetHandler.hpp +3 -3
- package/worker/include/RTC/SCTP/association/TransmissionControlBlock.hpp +3 -3
- package/worker/include/RTC/TcpServer.hpp +3 -2
- package/worker/include/RTC/UdpSocket.hpp +3 -2
- package/worker/meson.build +1 -0
- package/worker/src/RTC/DataConsumer.cpp +12 -2
- package/worker/src/RTC/PipeTransport.cpp +5 -4
- package/worker/src/RTC/PlainTransport.cpp +9 -8
- package/worker/src/RTC/PortManager.cpp +174 -114
- package/worker/src/RTC/SCTP/association/Association.cpp +17 -14
- package/worker/src/RTC/SCTP/association/HeartbeatHandler.cpp +15 -5
- package/worker/src/RTC/SCTP/association/StreamResetHandler.cpp +11 -6
- package/worker/src/RTC/SCTP/association/TransmissionControlBlock.cpp +15 -5
- package/worker/src/RTC/TcpServer.cpp +4 -4
- package/worker/src/RTC/Transport.cpp +33 -10
- package/worker/src/RTC/UdpSocket.cpp +4 -4
- package/worker/src/RTC/WebRtcServer.cpp +8 -8
- package/worker/src/RTC/WebRtcTransport.cpp +9 -8
- package/worker/tasks.py +293 -196
- package/worker/test/src/RTC/SCTP/association/TestHeartbeatHandler.cpp +4 -1
- package/worker/test/src/RTC/SCTP/association/TestTransmissionControlBlock.cpp +5 -2
- package/worker/test/src/RTC/TestNackGenerator.cpp +1 -1
- package/worker/test/src/RTC/TestPortManager.cpp +126 -0
- package/worker/test/src/RTC/TestTransportTuple.cpp +3 -2
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
#include "Logger.hpp"
|
|
7
7
|
#include "MediaSoupErrors.hpp"
|
|
8
8
|
#include "Utils.hpp"
|
|
9
|
-
#include <
|
|
9
|
+
#include <cstring> // std::memcmp(), std::memset()
|
|
10
|
+
#include <tuple> // std::make_tuple()
|
|
10
11
|
|
|
11
12
|
/* Static methods for UV callbacks. */
|
|
12
13
|
|
|
@@ -31,9 +32,11 @@ namespace RTC
|
|
|
31
32
|
{
|
|
32
33
|
/* Class variables. */
|
|
33
34
|
|
|
34
|
-
thread_local ankerl::unordered_dense::
|
|
35
|
+
thread_local ankerl::unordered_dense::
|
|
36
|
+
map<PortManager::PortRangeKey, PortManager::PortRange, PortManager::PortRangeKeyHash>
|
|
37
|
+
PortManager::mapPortRanges;
|
|
35
38
|
|
|
36
|
-
/*
|
|
39
|
+
/* PortManager class methods. */
|
|
37
40
|
|
|
38
41
|
uv_handle_t* PortManager::Bind(
|
|
39
42
|
Protocol protocol, std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags)
|
|
@@ -71,7 +74,8 @@ namespace RTC
|
|
|
71
74
|
{
|
|
72
75
|
case AF_INET:
|
|
73
76
|
{
|
|
74
|
-
err = uv_ip4_addr(
|
|
77
|
+
err = uv_ip4_addr(
|
|
78
|
+
ip.c_str(), 0, reinterpret_cast<struct sockaddr_in*>(std::addressof(bindAddr)));
|
|
75
79
|
|
|
76
80
|
if (err != 0)
|
|
77
81
|
{
|
|
@@ -83,7 +87,8 @@ namespace RTC
|
|
|
83
87
|
|
|
84
88
|
case AF_INET6:
|
|
85
89
|
{
|
|
86
|
-
err = uv_ip6_addr(
|
|
90
|
+
err = uv_ip6_addr(
|
|
91
|
+
ip.c_str(), 0, reinterpret_cast<struct sockaddr_in6*>(std::addressof(bindAddr)));
|
|
87
92
|
|
|
88
93
|
if (err != 0)
|
|
89
94
|
{
|
|
@@ -105,14 +110,14 @@ namespace RTC
|
|
|
105
110
|
{
|
|
106
111
|
case AF_INET:
|
|
107
112
|
{
|
|
108
|
-
(reinterpret_cast<struct sockaddr_in*>(
|
|
113
|
+
(reinterpret_cast<struct sockaddr_in*>(std::addressof(bindAddr)))->sin_port = htons(port);
|
|
109
114
|
|
|
110
115
|
break;
|
|
111
116
|
}
|
|
112
117
|
|
|
113
118
|
case AF_INET6:
|
|
114
119
|
{
|
|
115
|
-
(reinterpret_cast<struct sockaddr_in6*>(
|
|
120
|
+
(reinterpret_cast<struct sockaddr_in6*>(std::addressof(bindAddr)))->sin6_port = htons(port);
|
|
116
121
|
|
|
117
122
|
break;
|
|
118
123
|
}
|
|
@@ -175,7 +180,7 @@ namespace RTC
|
|
|
175
180
|
{
|
|
176
181
|
err = uv_udp_bind(
|
|
177
182
|
reinterpret_cast<uv_udp_t*>(uvHandle),
|
|
178
|
-
reinterpret_cast<const struct sockaddr*>(
|
|
183
|
+
reinterpret_cast<const struct sockaddr*>(std::addressof(bindAddr)),
|
|
179
184
|
bitFlags);
|
|
180
185
|
|
|
181
186
|
if (err != 0)
|
|
@@ -198,7 +203,7 @@ namespace RTC
|
|
|
198
203
|
{
|
|
199
204
|
err = uv_tcp_bind(
|
|
200
205
|
reinterpret_cast<uv_tcp_t*>(uvHandle),
|
|
201
|
-
reinterpret_cast<const struct sockaddr*>(
|
|
206
|
+
reinterpret_cast<const struct sockaddr*>(std::addressof(bindAddr)),
|
|
202
207
|
bitFlags);
|
|
203
208
|
|
|
204
209
|
if (err != 0)
|
|
@@ -250,7 +255,7 @@ namespace RTC
|
|
|
250
255
|
uint16_t minPort,
|
|
251
256
|
uint16_t maxPort,
|
|
252
257
|
RTC::Transport::SocketFlags& flags,
|
|
253
|
-
|
|
258
|
+
PortRangeKey& key)
|
|
254
259
|
{
|
|
255
260
|
MS_TRACE();
|
|
256
261
|
|
|
@@ -288,7 +293,8 @@ namespace RTC
|
|
|
288
293
|
{
|
|
289
294
|
case AF_INET:
|
|
290
295
|
{
|
|
291
|
-
err = uv_ip4_addr(
|
|
296
|
+
err = uv_ip4_addr(
|
|
297
|
+
ip.c_str(), 0, reinterpret_cast<struct sockaddr_in*>(std::addressof(bindAddr)));
|
|
292
298
|
|
|
293
299
|
if (err != 0)
|
|
294
300
|
{
|
|
@@ -300,7 +306,8 @@ namespace RTC
|
|
|
300
306
|
|
|
301
307
|
case AF_INET6:
|
|
302
308
|
{
|
|
303
|
-
err = uv_ip6_addr(
|
|
309
|
+
err = uv_ip6_addr(
|
|
310
|
+
ip.c_str(), 0, reinterpret_cast<struct sockaddr_in6*>(std::addressof(bindAddr)));
|
|
304
311
|
|
|
305
312
|
if (err != 0)
|
|
306
313
|
{
|
|
@@ -317,9 +324,9 @@ namespace RTC
|
|
|
317
324
|
}
|
|
318
325
|
}
|
|
319
326
|
|
|
320
|
-
|
|
327
|
+
key = PortRangeKey(protocol, bindAddr, minPort, maxPort);
|
|
321
328
|
|
|
322
|
-
auto& portRange = PortManager::GetOrCreatePortRange(
|
|
329
|
+
auto& portRange = PortManager::GetOrCreatePortRange(key, minPort, maxPort);
|
|
323
330
|
const size_t numPorts = portRange.ports.size();
|
|
324
331
|
const size_t numAttempts = numPorts;
|
|
325
332
|
size_t attempt{ 0u };
|
|
@@ -385,14 +392,14 @@ namespace RTC
|
|
|
385
392
|
{
|
|
386
393
|
case AF_INET:
|
|
387
394
|
{
|
|
388
|
-
(reinterpret_cast<struct sockaddr_in*>(
|
|
395
|
+
(reinterpret_cast<struct sockaddr_in*>(std::addressof(bindAddr)))->sin_port = htons(port);
|
|
389
396
|
|
|
390
397
|
break;
|
|
391
398
|
}
|
|
392
399
|
|
|
393
400
|
case AF_INET6:
|
|
394
401
|
{
|
|
395
|
-
(reinterpret_cast<struct sockaddr_in6*>(
|
|
402
|
+
(reinterpret_cast<struct sockaddr_in6*>(std::addressof(bindAddr)))->sin6_port = htons(port);
|
|
396
403
|
|
|
397
404
|
break;
|
|
398
405
|
}
|
|
@@ -455,7 +462,7 @@ namespace RTC
|
|
|
455
462
|
{
|
|
456
463
|
err = uv_udp_bind(
|
|
457
464
|
reinterpret_cast<uv_udp_t*>(uvHandle),
|
|
458
|
-
reinterpret_cast<const struct sockaddr*>(
|
|
465
|
+
reinterpret_cast<const struct sockaddr*>(std::addressof(bindAddr)),
|
|
459
466
|
bitFlags);
|
|
460
467
|
|
|
461
468
|
if (err != 0)
|
|
@@ -477,7 +484,7 @@ namespace RTC
|
|
|
477
484
|
{
|
|
478
485
|
err = uv_tcp_bind(
|
|
479
486
|
reinterpret_cast<uv_tcp_t*>(uvHandle),
|
|
480
|
-
reinterpret_cast<const struct sockaddr*>(
|
|
487
|
+
reinterpret_cast<const struct sockaddr*>(std::addressof(bindAddr)),
|
|
481
488
|
bitFlags);
|
|
482
489
|
|
|
483
490
|
if (err != 0)
|
|
@@ -595,16 +602,19 @@ namespace RTC
|
|
|
595
602
|
return uvHandle;
|
|
596
603
|
}
|
|
597
604
|
|
|
598
|
-
void PortManager::Unbind(
|
|
605
|
+
void PortManager::Unbind(const PortRangeKey& key, uint16_t port)
|
|
599
606
|
{
|
|
600
607
|
MS_TRACE();
|
|
601
608
|
|
|
602
|
-
auto it = PortManager::mapPortRanges.find(
|
|
609
|
+
auto it = PortManager::mapPortRanges.find(key);
|
|
603
610
|
|
|
604
611
|
// This should not happen.
|
|
605
612
|
if (it == PortManager::mapPortRanges.end())
|
|
606
613
|
{
|
|
607
|
-
MS_ERROR(
|
|
614
|
+
MS_ERROR(
|
|
615
|
+
"port range key [minPort:%" PRIu16 ", maxPort:%" PRIu16 "] doesn't exist in the map",
|
|
616
|
+
key.minPort,
|
|
617
|
+
key.maxPort);
|
|
608
618
|
|
|
609
619
|
return;
|
|
610
620
|
}
|
|
@@ -633,13 +643,15 @@ namespace RTC
|
|
|
633
643
|
{
|
|
634
644
|
MS_DUMP_CLEAN(indentation, "<PortManager>");
|
|
635
645
|
|
|
636
|
-
for (auto& kv : PortManager::mapPortRanges)
|
|
646
|
+
for (const auto& kv : PortManager::mapPortRanges)
|
|
637
647
|
{
|
|
638
|
-
auto
|
|
639
|
-
auto portRange
|
|
648
|
+
const auto& key = kv.first;
|
|
649
|
+
const auto& portRange = kv.second;
|
|
650
|
+
const char* protocolStr = (key.protocol == Protocol::UDP) ? "udp" : "tcp";
|
|
640
651
|
|
|
641
652
|
MS_DUMP_CLEAN(indentation + 1, "<PortRange>");
|
|
642
|
-
MS_DUMP_CLEAN(indentation + 1, "
|
|
653
|
+
MS_DUMP_CLEAN(indentation + 1, " protocol: %s", protocolStr);
|
|
654
|
+
MS_DUMP_CLEAN(indentation + 1, " family: %d", key.bindAddr.ss_family);
|
|
643
655
|
MS_DUMP_CLEAN(indentation + 1, " minPort: %" PRIu16, portRange.minPort);
|
|
644
656
|
MS_DUMP_CLEAN(indentation + 1, " maxPort: %zu", portRange.minPort + portRange.ports.size() - 1);
|
|
645
657
|
MS_DUMP_CLEAN(indentation + 1, " numUsedPorts: %" PRIu16, portRange.numUsedPorts);
|
|
@@ -649,95 +661,14 @@ namespace RTC
|
|
|
649
661
|
MS_DUMP_CLEAN(indentation, "</PortManager>");
|
|
650
662
|
}
|
|
651
663
|
|
|
652
|
-
/*
|
|
653
|
-
* Hash for IPv4.
|
|
654
|
-
*
|
|
655
|
-
* 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
|
|
656
|
-
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
657
|
-
* | MIN PORT | MAX PORT |
|
|
658
|
-
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
659
|
-
* | IP | IP >> 2 |F|P|
|
|
660
|
-
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
661
|
-
*
|
|
662
|
-
* Hash for IPv6.
|
|
663
|
-
*
|
|
664
|
-
* 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
|
|
665
|
-
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
666
|
-
* | MIN PORT | MAX PORT |
|
|
667
|
-
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
668
|
-
* |IP[0] ^ IP[1] ^ IP[2] ^ IP[3] | same >> 2 |F|P|
|
|
669
|
-
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
670
|
-
*/
|
|
671
|
-
uint64_t PortManager::GeneratePortRangeHash(
|
|
672
|
-
Protocol protocol, sockaddr_storage* bindAddr, uint16_t minPort, uint16_t maxPort)
|
|
673
|
-
{
|
|
674
|
-
MS_TRACE();
|
|
675
|
-
|
|
676
|
-
uint64_t hash{ 0u };
|
|
677
|
-
|
|
678
|
-
switch (bindAddr->ss_family)
|
|
679
|
-
{
|
|
680
|
-
case AF_INET:
|
|
681
|
-
{
|
|
682
|
-
auto* bindAddrIn = reinterpret_cast<struct sockaddr_in*>(bindAddr);
|
|
683
|
-
|
|
684
|
-
// We want it in network order.
|
|
685
|
-
const uint64_t address = bindAddrIn->sin_addr.s_addr;
|
|
686
|
-
|
|
687
|
-
hash |= static_cast<uint64_t>(minPort) << 48;
|
|
688
|
-
hash |= static_cast<uint64_t>(maxPort) << 32;
|
|
689
|
-
hash |= (address >> 2) << 2;
|
|
690
|
-
hash |= 0x0000; // AF_INET.
|
|
691
|
-
|
|
692
|
-
break;
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
case AF_INET6:
|
|
696
|
-
{
|
|
697
|
-
auto* bindAddrIn6 = reinterpret_cast<struct sockaddr_in6*>(bindAddr);
|
|
698
|
-
auto* a = reinterpret_cast<uint32_t*>(std::addressof(bindAddrIn6->sin6_addr));
|
|
699
|
-
|
|
700
|
-
const auto address = a[0] ^ a[1] ^ a[2] ^ a[3];
|
|
701
|
-
|
|
702
|
-
hash |= static_cast<uint64_t>(minPort) << 48;
|
|
703
|
-
hash |= static_cast<uint64_t>(maxPort) << 32;
|
|
704
|
-
hash |= static_cast<uint64_t>(address) << 16;
|
|
705
|
-
hash |= (static_cast<uint64_t>(address) >> 2) << 2;
|
|
706
|
-
hash |= 0x0002; // AF_INET6.
|
|
707
|
-
|
|
708
|
-
break;
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
// This cannot happen.
|
|
712
|
-
default:
|
|
713
|
-
{
|
|
714
|
-
MS_THROW_ERROR("unknown IP family");
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
// Override least significant bit with protocol information:
|
|
719
|
-
// - If UDP, start with 0.
|
|
720
|
-
// - If TCP, start with 1.
|
|
721
|
-
if (protocol == Protocol::UDP)
|
|
722
|
-
{
|
|
723
|
-
hash |= 0x0000;
|
|
724
|
-
}
|
|
725
|
-
else
|
|
726
|
-
{
|
|
727
|
-
hash |= 0x0001;
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
return hash;
|
|
731
|
-
}
|
|
732
|
-
|
|
733
664
|
PortManager::PortRange& PortManager::GetOrCreatePortRange(
|
|
734
|
-
|
|
665
|
+
const PortRangeKey& key, uint16_t minPort, uint16_t maxPort)
|
|
735
666
|
{
|
|
736
667
|
MS_TRACE();
|
|
737
668
|
|
|
738
|
-
auto it = PortManager::mapPortRanges.find(
|
|
669
|
+
const auto it = PortManager::mapPortRanges.find(key);
|
|
739
670
|
|
|
740
|
-
// If the
|
|
671
|
+
// If the key is already handled, return its port range.
|
|
741
672
|
if (it != PortManager::mapPortRanges.end())
|
|
742
673
|
{
|
|
743
674
|
auto& portRange = it->second;
|
|
@@ -747,10 +678,10 @@ namespace RTC
|
|
|
747
678
|
|
|
748
679
|
const uint16_t numPorts = maxPort - minPort + 1;
|
|
749
680
|
|
|
750
|
-
// Emplace a new vector filled with numPorts false values, meaning that
|
|
681
|
+
// Emplace a new vector filled with `numPorts` false values, meaning that
|
|
751
682
|
// all ports are available.
|
|
752
|
-
auto pair = PortManager::mapPortRanges.emplace(
|
|
753
|
-
std::piecewise_construct, std::
|
|
683
|
+
const auto pair = PortManager::mapPortRanges.emplace(
|
|
684
|
+
std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(numPorts, minPort));
|
|
754
685
|
|
|
755
686
|
// pair.first is an iterator to the inserted value.
|
|
756
687
|
auto& portRange = pair.first->second;
|
|
@@ -764,7 +695,7 @@ namespace RTC
|
|
|
764
695
|
|
|
765
696
|
uint8_t bitFlags{ 0b00000000 };
|
|
766
697
|
|
|
767
|
-
// Ignore ipv6Only in IPv4, otherwise libuv will throw.
|
|
698
|
+
// Ignore `ipv6Only` in IPv4, otherwise libuv will throw.
|
|
768
699
|
if (flags.ipv6Only && family == AF_INET6)
|
|
769
700
|
{
|
|
770
701
|
switch (protocol)
|
|
@@ -785,7 +716,7 @@ namespace RTC
|
|
|
785
716
|
}
|
|
786
717
|
}
|
|
787
718
|
|
|
788
|
-
// Ignore udpReusePort in TCP, otherwise libuv will throw.
|
|
719
|
+
// Ignore `udpReusePort` in TCP, otherwise libuv will throw.
|
|
789
720
|
if (flags.udpReusePort && protocol == Protocol::UDP)
|
|
790
721
|
{
|
|
791
722
|
bitFlags |= UV_UDP_REUSEADDR;
|
|
@@ -793,4 +724,133 @@ namespace RTC
|
|
|
793
724
|
|
|
794
725
|
return bitFlags;
|
|
795
726
|
}
|
|
727
|
+
|
|
728
|
+
/* PortRangeKey instance methods. */
|
|
729
|
+
|
|
730
|
+
PortManager::PortRangeKey::PortRangeKey(
|
|
731
|
+
Protocol protocol, const sockaddr_storage& bindAddr, uint16_t minPort, uint16_t maxPort)
|
|
732
|
+
: protocol(protocol), bindAddr(bindAddr), minPort(minPort), maxPort(maxPort)
|
|
733
|
+
{
|
|
734
|
+
MS_TRACE();
|
|
735
|
+
|
|
736
|
+
// `sockaddr_storage` is padded; the unused tail bytes are caller-controlled.
|
|
737
|
+
// `operator==` inspects only the meaningful address bytes (`sin_addr` /
|
|
738
|
+
// `sin6_addr`) so padding does not affect equality, and the hash function
|
|
739
|
+
// hashes the same exact fields, so two structurally-equal keys always
|
|
740
|
+
// produce the same hash regardless of how the caller zero-initialized.
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
bool PortManager::PortRangeKey::operator==(const PortRangeKey& other) const noexcept
|
|
744
|
+
{
|
|
745
|
+
MS_TRACE();
|
|
746
|
+
|
|
747
|
+
if (this->protocol != other.protocol)
|
|
748
|
+
{
|
|
749
|
+
return false;
|
|
750
|
+
}
|
|
751
|
+
else if (this->minPort != other.minPort)
|
|
752
|
+
{
|
|
753
|
+
return false;
|
|
754
|
+
}
|
|
755
|
+
else if (this->maxPort != other.maxPort)
|
|
756
|
+
{
|
|
757
|
+
return false;
|
|
758
|
+
}
|
|
759
|
+
else if (this->bindAddr.ss_family != other.bindAddr.ss_family)
|
|
760
|
+
{
|
|
761
|
+
return false;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
switch (this->bindAddr.ss_family)
|
|
765
|
+
{
|
|
766
|
+
case AF_INET:
|
|
767
|
+
{
|
|
768
|
+
const auto* a = reinterpret_cast<const sockaddr_in*>(std::addressof(this->bindAddr));
|
|
769
|
+
const auto* b = reinterpret_cast<const sockaddr_in*>(std::addressof(other.bindAddr));
|
|
770
|
+
|
|
771
|
+
return a->sin_addr.s_addr == b->sin_addr.s_addr;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
case AF_INET6:
|
|
775
|
+
{
|
|
776
|
+
const auto* a = reinterpret_cast<const sockaddr_in6*>(std::addressof(this->bindAddr));
|
|
777
|
+
const auto* b = reinterpret_cast<const sockaddr_in6*>(std::addressof(other.bindAddr));
|
|
778
|
+
|
|
779
|
+
return std::memcmp(
|
|
780
|
+
std::addressof(a->sin6_addr), std::addressof(b->sin6_addr), sizeof(in6_addr)) == 0;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
default:
|
|
784
|
+
{
|
|
785
|
+
// Unknown family; treat as not equal to avoid accidental merge.
|
|
786
|
+
return false;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
/* PortRangeKeyHash instance methods. */
|
|
792
|
+
|
|
793
|
+
size_t PortManager::PortRangeKeyHash::operator()(const PortRangeKey& key) const noexcept
|
|
794
|
+
{
|
|
795
|
+
MS_TRACE();
|
|
796
|
+
|
|
797
|
+
const auto protocolBits = static_cast<uint8_t>(key.protocol);
|
|
798
|
+
const auto familyBits = static_cast<uint16_t>(key.bindAddr.ss_family);
|
|
799
|
+
|
|
800
|
+
auto hashCombine = [](size_t& seed, size_t value)
|
|
801
|
+
{
|
|
802
|
+
seed ^= value + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
|
803
|
+
};
|
|
804
|
+
|
|
805
|
+
size_t seed = 0;
|
|
806
|
+
|
|
807
|
+
switch (key.bindAddr.ss_family)
|
|
808
|
+
{
|
|
809
|
+
case AF_INET:
|
|
810
|
+
{
|
|
811
|
+
const auto* in = reinterpret_cast<const sockaddr_in*>(std::addressof(key.bindAddr));
|
|
812
|
+
|
|
813
|
+
hashCombine(seed, ankerl::unordered_dense::hash<uint8_t>{}(protocolBits));
|
|
814
|
+
hashCombine(seed, ankerl::unordered_dense::hash<uint16_t>{}(familyBits));
|
|
815
|
+
hashCombine(seed, ankerl::unordered_dense::hash<uint32_t>{}(in->sin_addr.s_addr));
|
|
816
|
+
hashCombine(seed, ankerl::unordered_dense::hash<uint16_t>{}(key.minPort));
|
|
817
|
+
hashCombine(seed, ankerl::unordered_dense::hash<uint16_t>{}(key.maxPort));
|
|
818
|
+
|
|
819
|
+
break;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
case AF_INET6:
|
|
823
|
+
{
|
|
824
|
+
const auto* in6 = reinterpret_cast<const sockaddr_in6*>(std::addressof(key.bindAddr));
|
|
825
|
+
const auto* addr = in6->sin6_addr.s6_addr;
|
|
826
|
+
|
|
827
|
+
uint64_t hi;
|
|
828
|
+
uint64_t lo;
|
|
829
|
+
|
|
830
|
+
std::memcpy(std::addressof(hi), addr, sizeof(uint64_t));
|
|
831
|
+
std::memcpy(std::addressof(lo), addr + sizeof(uint64_t), sizeof(uint64_t));
|
|
832
|
+
|
|
833
|
+
hashCombine(seed, ankerl::unordered_dense::hash<uint8_t>{}(protocolBits));
|
|
834
|
+
hashCombine(seed, ankerl::unordered_dense::hash<uint16_t>{}(familyBits));
|
|
835
|
+
hashCombine(seed, ankerl::unordered_dense::hash<uint64_t>{}(hi));
|
|
836
|
+
hashCombine(seed, ankerl::unordered_dense::hash<uint64_t>{}(lo));
|
|
837
|
+
hashCombine(seed, ankerl::unordered_dense::hash<uint16_t>{}(key.minPort));
|
|
838
|
+
hashCombine(seed, ankerl::unordered_dense::hash<uint16_t>{}(key.maxPort));
|
|
839
|
+
|
|
840
|
+
break;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
default:
|
|
844
|
+
{
|
|
845
|
+
hashCombine(seed, ankerl::unordered_dense::hash<uint8_t>{}(protocolBits));
|
|
846
|
+
hashCombine(seed, ankerl::unordered_dense::hash<uint16_t>{}(familyBits));
|
|
847
|
+
hashCombine(seed, ankerl::unordered_dense::hash<uint16_t>{}(key.minPort));
|
|
848
|
+
hashCombine(seed, ankerl::unordered_dense::hash<uint16_t>{}(key.maxPort));
|
|
849
|
+
|
|
850
|
+
break;
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
return seed;
|
|
855
|
+
}
|
|
796
856
|
} // namespace RTC
|
|
@@ -1104,11 +1104,12 @@ namespace RTC
|
|
|
1104
1104
|
{
|
|
1105
1105
|
MS_WARN_TAG(
|
|
1106
1106
|
sctp,
|
|
1107
|
-
"ABORT chunk verification tag %" PRIu32 "
|
|
1107
|
+
"receievd ABORT chunk has invalid verification tag %" PRIu32 ", packet discarded",
|
|
1108
1108
|
receivedPacket->GetVerificationTag());
|
|
1109
1109
|
|
|
1110
1110
|
this->associationListenerDeferrer.OnAssociationError(
|
|
1111
|
-
Types::ErrorKind::PARSE_FAILED,
|
|
1111
|
+
Types::ErrorKind::PARSE_FAILED,
|
|
1112
|
+
"received packet with ABORT chunk has invalid verification tag");
|
|
1112
1113
|
|
|
1113
1114
|
return false;
|
|
1114
1115
|
}
|
|
@@ -1124,13 +1125,14 @@ namespace RTC
|
|
|
1124
1125
|
{
|
|
1125
1126
|
MS_WARN_TAG(
|
|
1126
1127
|
sctp,
|
|
1127
|
-
"INIT-ACK chunk verification tag %" PRIu32 " (should be %" PRIu32
|
|
1128
|
+
"received INIT-ACK chunk has invalid verification tag %" PRIu32 " (should be %" PRIu32
|
|
1129
|
+
"), packet discarded",
|
|
1128
1130
|
receivedPacket->GetVerificationTag(),
|
|
1129
1131
|
this->preTcb.localVerificationTag);
|
|
1130
1132
|
|
|
1131
1133
|
this->associationListenerDeferrer.OnAssociationError(
|
|
1132
1134
|
Types::ErrorKind::PARSE_FAILED,
|
|
1133
|
-
"packet with INIT-ACK chunk has invalid verification tag");
|
|
1135
|
+
"received packet with INIT-ACK chunk has invalid verification tag");
|
|
1134
1136
|
|
|
1135
1137
|
return false;
|
|
1136
1138
|
}
|
|
@@ -1173,12 +1175,13 @@ namespace RTC
|
|
|
1173
1175
|
{
|
|
1174
1176
|
MS_WARN_TAG(
|
|
1175
1177
|
sctp,
|
|
1176
|
-
"SHUTDOWN-COMPLETE chunk verification tag %" PRIu32
|
|
1178
|
+
"received SHUTDOWN-COMPLETE chunk has invalid verification tag %" PRIu32
|
|
1179
|
+
", packet discarded",
|
|
1177
1180
|
receivedPacket->GetVerificationTag());
|
|
1178
1181
|
|
|
1179
1182
|
this->associationListenerDeferrer.OnAssociationError(
|
|
1180
1183
|
Types::ErrorKind::PARSE_FAILED,
|
|
1181
|
-
"packet with SHUTDOWN-COMPLETE chunk has invalid verification tag");
|
|
1184
|
+
"received packet with SHUTDOWN-COMPLETE chunk has invalid verification tag");
|
|
1182
1185
|
|
|
1183
1186
|
return false;
|
|
1184
1187
|
}
|
|
@@ -1200,7 +1203,8 @@ namespace RTC
|
|
|
1200
1203
|
{
|
|
1201
1204
|
MS_WARN_TAG(
|
|
1202
1205
|
sctp,
|
|
1203
|
-
"invalid verification tag %" PRIu32 " (should be %" PRIu32
|
|
1206
|
+
"received packet has invalid verification tag %" PRIu32 " (should be %" PRIu32
|
|
1207
|
+
"), packet discarded",
|
|
1204
1208
|
receivedPacket->GetVerificationTag(),
|
|
1205
1209
|
localVerificationTag);
|
|
1206
1210
|
|
|
@@ -1369,7 +1373,7 @@ namespace RTC
|
|
|
1369
1373
|
// be 0, the receiver MUST silently discard the packet."
|
|
1370
1374
|
if (receivedInitChunk->GetInitiateTag() == 0)
|
|
1371
1375
|
{
|
|
1372
|
-
MS_WARN_TAG(sctp, "invalid value 0 in Initiate
|
|
1376
|
+
MS_WARN_TAG(sctp, "invalid value 0 in Initiate Tag in received INIT chunk, packet discarded");
|
|
1373
1377
|
|
|
1374
1378
|
return;
|
|
1375
1379
|
}
|
|
@@ -1388,7 +1392,7 @@ namespace RTC
|
|
|
1388
1392
|
{
|
|
1389
1393
|
MS_WARN_TAG(
|
|
1390
1394
|
sctp,
|
|
1391
|
-
"invalid number of outbound streams or
|
|
1395
|
+
"invalid number of outbound streams or number of inbound streams in received INIT chunk, aborting association");
|
|
1392
1396
|
|
|
1393
1397
|
auto packet = CreatePacketWithVerificationTag(0);
|
|
1394
1398
|
auto* abortAssociationChunk = packet->BuildChunkInPlace<AbortAssociationChunk>();
|
|
@@ -1557,7 +1561,7 @@ namespace RTC
|
|
|
1557
1561
|
// INIT ACK chunk."
|
|
1558
1562
|
if (this->state != State::COOKIE_WAIT)
|
|
1559
1563
|
{
|
|
1560
|
-
MS_DEBUG_TAG(sctp, "ignoring
|
|
1564
|
+
MS_DEBUG_TAG(sctp, "ignoring INIT-ACK chunk when not in COOKIE_WAIT state");
|
|
1561
1565
|
|
|
1562
1566
|
return;
|
|
1563
1567
|
}
|
|
@@ -1567,8 +1571,7 @@ namespace RTC
|
|
|
1567
1571
|
|
|
1568
1572
|
if (!stateCookieParameter || !stateCookieParameter->GetCookie())
|
|
1569
1573
|
{
|
|
1570
|
-
MS_WARN_TAG(
|
|
1571
|
-
sctp, "ignoring received INIT-ACK chunk without StateCookieParameter or without cookie");
|
|
1574
|
+
MS_WARN_TAG(sctp, "ignoring INIT-ACK chunk without StateCookieParameter or without cookie");
|
|
1572
1575
|
|
|
1573
1576
|
auto packet = CreatePacketWithVerificationTag(this->preTcb.localVerificationTag);
|
|
1574
1577
|
auto* abortAssociationChunk = packet->BuildChunkInPlace<AbortAssociationChunk>();
|
|
@@ -1643,10 +1646,10 @@ namespace RTC
|
|
|
1643
1646
|
|
|
1644
1647
|
if (!receivedCookieEchoChunk->HasCookie())
|
|
1645
1648
|
{
|
|
1646
|
-
MS_WARN_TAG(sctp, "ignoring
|
|
1649
|
+
MS_WARN_TAG(sctp, "ignoring invalid COOKIE-ECHO chunk without cookie");
|
|
1647
1650
|
|
|
1648
1651
|
this->associationListenerDeferrer.OnAssociationError(
|
|
1649
|
-
Types::ErrorKind::PARSE_FAILED, "received COOKIE-ECHO chunk
|
|
1652
|
+
Types::ErrorKind::PARSE_FAILED, "received COOKIE-ECHO chunk has no cookie");
|
|
1650
1653
|
|
|
1651
1654
|
return;
|
|
1652
1655
|
}
|
|
@@ -19,11 +19,11 @@ namespace RTC
|
|
|
19
19
|
/* Instance methods. */
|
|
20
20
|
|
|
21
21
|
HeartbeatHandler::HeartbeatHandler(
|
|
22
|
-
|
|
22
|
+
AssociationListenerDeferrer& associationListenerDeferrer,
|
|
23
23
|
const SctpOptions& sctpOptions,
|
|
24
24
|
SharedInterface* shared,
|
|
25
25
|
TransmissionControlBlockContextInterface* tcbContext)
|
|
26
|
-
:
|
|
26
|
+
: associationListenerDeferrer(associationListenerDeferrer),
|
|
27
27
|
sctpOptions(sctpOptions),
|
|
28
28
|
shared(shared),
|
|
29
29
|
tcbContext(tcbContext),
|
|
@@ -124,7 +124,7 @@ namespace RTC
|
|
|
124
124
|
|
|
125
125
|
if (!heartbeatInfoParameter)
|
|
126
126
|
{
|
|
127
|
-
this->
|
|
127
|
+
this->associationListenerDeferrer.OnAssociationError(
|
|
128
128
|
Types::ErrorKind::PARSE_FAILED,
|
|
129
129
|
"ignoring HEARTBEAT-ACK chunk without Heartbeat Info parameter");
|
|
130
130
|
|
|
@@ -136,14 +136,14 @@ namespace RTC
|
|
|
136
136
|
|
|
137
137
|
if (!info)
|
|
138
138
|
{
|
|
139
|
-
this->
|
|
139
|
+
this->associationListenerDeferrer.OnAssociationError(
|
|
140
140
|
Types::ErrorKind::PARSE_FAILED, "ignoring Heartbeat Info parameter without info field");
|
|
141
141
|
|
|
142
142
|
return;
|
|
143
143
|
}
|
|
144
144
|
else if (infoLen != HeartbeatInfoLength)
|
|
145
145
|
{
|
|
146
|
-
this->
|
|
146
|
+
this->associationListenerDeferrer.OnAssociationError(
|
|
147
147
|
Types::ErrorKind::PARSE_FAILED, "ignoring Heartbeat Info parameter with wrong length");
|
|
148
148
|
|
|
149
149
|
return;
|
|
@@ -180,6 +180,11 @@ namespace RTC
|
|
|
180
180
|
{
|
|
181
181
|
MS_TRACE();
|
|
182
182
|
|
|
183
|
+
// This is a top-level timer entry point (invoked by libuv outside any other
|
|
184
|
+
// SCTP API call), so it must establish the deferrer scope itself, just like
|
|
185
|
+
// Association does in its own timer handlers.
|
|
186
|
+
const AssociationListenerDeferrer::ScopedDeferrer deferrer(this->associationListenerDeferrer);
|
|
187
|
+
|
|
183
188
|
if (!this->tcbContext->IsAssociationEstablished())
|
|
184
189
|
{
|
|
185
190
|
MS_DEBUG_DEV("won't send HEARTBEAT-REQUEST when SCTP association is not established");
|
|
@@ -214,6 +219,11 @@ namespace RTC
|
|
|
214
219
|
{
|
|
215
220
|
MS_TRACE();
|
|
216
221
|
|
|
222
|
+
// This is a top-level timer entry point (invoked by libuv outside any other
|
|
223
|
+
// SCTP API call), so it must establish the deferrer scope itself, just like
|
|
224
|
+
// Association does in its own timer handlers.
|
|
225
|
+
const AssociationListenerDeferrer::ScopedDeferrer deferrer(this->associationListenerDeferrer);
|
|
226
|
+
|
|
217
227
|
// Note that the timeout timer is not restarted. It will be started again when
|
|
218
228
|
// the interval timer expires.
|
|
219
229
|
MS_ASSERT(!this->timeoutTimer->IsRunning(), "timeout timer shouldn't be running");
|
|
@@ -13,13 +13,13 @@ namespace RTC
|
|
|
13
13
|
/* Instance methods. */
|
|
14
14
|
|
|
15
15
|
StreamResetHandler::StreamResetHandler(
|
|
16
|
-
|
|
16
|
+
AssociationListenerDeferrer& associationListenerDeferrer,
|
|
17
17
|
SharedInterface* shared,
|
|
18
18
|
TransmissionControlBlockContextInterface* tcbContext,
|
|
19
19
|
DataTracker* dataTracker,
|
|
20
20
|
ReassemblyQueue* reassemblyQueue,
|
|
21
21
|
RetransmissionQueue* retransmissionQueue)
|
|
22
|
-
:
|
|
22
|
+
: associationListenerDeferrer(associationListenerDeferrer),
|
|
23
23
|
shared(shared),
|
|
24
24
|
tcbContext(tcbContext),
|
|
25
25
|
dataTracker(dataTracker),
|
|
@@ -89,7 +89,7 @@ namespace RTC
|
|
|
89
89
|
|
|
90
90
|
if (!ValidateReceivedReConfigChunk(receivedReConfigChunk))
|
|
91
91
|
{
|
|
92
|
-
this->
|
|
92
|
+
this->associationListenerDeferrer.OnAssociationError(
|
|
93
93
|
Types::ErrorKind::PARSE_FAILED, "invalid RE-CONFIG command received");
|
|
94
94
|
|
|
95
95
|
return;
|
|
@@ -334,7 +334,7 @@ namespace RTC
|
|
|
334
334
|
this->reassemblyQueue->ResetStreamsAndLeaveDeferredReset(
|
|
335
335
|
receivedOutgoingSsnResetRequestParameter->GetStreamIds());
|
|
336
336
|
|
|
337
|
-
this->
|
|
337
|
+
this->associationListenerDeferrer.OnAssociationInboundStreamsReset(
|
|
338
338
|
receivedOutgoingSsnResetRequestParameter->GetStreamIds());
|
|
339
339
|
|
|
340
340
|
this->lastProcessedReqResult = ReconfigurationResponseParameter::Result::SUCCESS_PERFORMED;
|
|
@@ -412,7 +412,7 @@ namespace RTC
|
|
|
412
412
|
MS_DEBUG_DEV(
|
|
413
413
|
"reset stream success [reqSeqNbr:%" PRIu32 "]", this->currentRequest->GetReqSeqNbr());
|
|
414
414
|
|
|
415
|
-
this->
|
|
415
|
+
this->associationListenerDeferrer.OnAssociationStreamsResetPerformed(
|
|
416
416
|
this->currentRequest->GetStreamIds());
|
|
417
417
|
|
|
418
418
|
this->currentRequest = std::nullopt;
|
|
@@ -450,7 +450,7 @@ namespace RTC
|
|
|
450
450
|
receivedReconfigurationResponseParameter->GetResult())
|
|
451
451
|
.c_str());
|
|
452
452
|
|
|
453
|
-
this->
|
|
453
|
+
this->associationListenerDeferrer.OnAssociationStreamsResetFailed(
|
|
454
454
|
this->currentRequest->GetStreamIds(),
|
|
455
455
|
ReconfigurationResponseParameter::ResultToString(
|
|
456
456
|
receivedReconfigurationResponseParameter->GetResult()));
|
|
@@ -469,6 +469,11 @@ namespace RTC
|
|
|
469
469
|
{
|
|
470
470
|
MS_TRACE();
|
|
471
471
|
|
|
472
|
+
// This is a top-level timer entry point (invoked by libuv outside any other
|
|
473
|
+
// SCTP API call), so it must establish the deferrer scope itself, just like
|
|
474
|
+
// Association does in its own timer handlers.
|
|
475
|
+
const AssociationListenerDeferrer::ScopedDeferrer deferrer(this->associationListenerDeferrer);
|
|
476
|
+
|
|
472
477
|
if (this->currentRequest && this->currentRequest->HasBeenSent())
|
|
473
478
|
{
|
|
474
479
|
// The request was deferred (received "In Progress"). This is not a
|