mediasoup 3.20.8 → 3.20.10

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 (145) hide show
  1. package/README.md +14 -2
  2. package/node/lib/WebRtcServer.d.ts.map +1 -1
  3. package/node/lib/WebRtcServer.js +0 -7
  4. package/node/lib/WebRtcServerTypes.d.ts +0 -5
  5. package/node/lib/WebRtcServerTypes.d.ts.map +1 -1
  6. package/node/lib/Worker.d.ts +1 -1
  7. package/node/lib/Worker.d.ts.map +1 -1
  8. package/node/lib/Worker.js +1 -11
  9. package/node/lib/WorkerTypes.d.ts +0 -9
  10. package/node/lib/WorkerTypes.d.ts.map +1 -1
  11. package/node/lib/fbs/plain-transport/connect-response.d.ts.map +1 -1
  12. package/node/lib/fbs/plain-transport/connect-response.js +0 -1
  13. package/node/lib/fbs/web-rtc-server/dump-response.d.ts +2 -9
  14. package/node/lib/fbs/web-rtc-server/dump-response.d.ts.map +1 -1
  15. package/node/lib/fbs/web-rtc-server/dump-response.js +5 -33
  16. package/node/lib/fbs/web-rtc-server.d.ts +0 -1
  17. package/node/lib/fbs/web-rtc-server.d.ts.map +1 -1
  18. package/node/lib/fbs/web-rtc-server.js +1 -4
  19. package/node/lib/fbs/worker/dump-response.d.ts +1 -5
  20. package/node/lib/fbs/worker/dump-response.d.ts.map +1 -1
  21. package/node/lib/fbs/worker/dump-response.js +3 -16
  22. package/node/lib/index.d.ts +1 -1
  23. package/node/lib/index.d.ts.map +1 -1
  24. package/node/lib/index.js +1 -2
  25. package/node/lib/test/test-PlainTransport.js +30 -0
  26. package/node/lib/test/test-WebRtcServer.js +0 -7
  27. package/node/lib/test/test-Worker.js +0 -1
  28. package/npm-scripts.mjs +177 -60
  29. package/package.json +10 -8
  30. package/worker/fbs/webRtcServer.fbs +0 -6
  31. package/worker/include/RTC/ICE/StunPacket.hpp +21 -2
  32. package/worker/include/RTC/NackGenerator.hpp +2 -2
  33. package/worker/include/RTC/RTP/RtpStreamRecv.hpp +2 -2
  34. package/worker/include/RTC/TransportTuple.hpp +70 -14
  35. package/worker/include/RTC/WebRtcServer.hpp +5 -2
  36. package/worker/include/Utils.hpp +6 -0
  37. package/worker/src/RTC/ICE/IceServer.cpp +2 -1
  38. package/worker/src/RTC/ICE/StunPacket.cpp +8 -0
  39. package/worker/src/RTC/NackGenerator.cpp +1 -1
  40. package/worker/src/RTC/PortManager.cpp +16 -20
  41. package/worker/src/RTC/Producer.cpp +1 -1
  42. package/worker/src/RTC/SeqManager.cpp +5 -4
  43. package/worker/src/RTC/TransportTuple.cpp +87 -50
  44. package/worker/src/RTC/WebRtcServer.cpp +20 -29
  45. package/worker/test/src/RTC/ICE/TestStunPacket.cpp +6 -2
  46. package/worker/test/src/RTC/RTP/TestRtpStreamRecv.cpp +1 -1
  47. package/worker/test/src/RTC/TestNackGenerator.cpp +1 -1
  48. package/worker/test/src/RTC/TestSeqManager.cpp +167 -62
  49. package/worker/test/src/RTC/TestTransportTuple.cpp +21 -14
  50. package/node/lib/fbs/data-consumer/binary.d.ts +0 -25
  51. package/node/lib/fbs/data-consumer/binary.d.ts.map +0 -1
  52. package/node/lib/fbs/data-consumer/binary.js +0 -110
  53. package/node/lib/fbs/data-consumer/data.d.ts +0 -10
  54. package/node/lib/fbs/data-consumer/data.d.ts.map +0 -1
  55. package/node/lib/fbs/data-consumer/data.js +0 -30
  56. package/node/lib/fbs/data-consumer/string.d.ts +0 -22
  57. package/node/lib/fbs/data-consumer/string.d.ts.map +0 -1
  58. package/node/lib/fbs/data-consumer/string.js +0 -92
  59. package/node/lib/fbs/data-producer/binary.d.ts +0 -25
  60. package/node/lib/fbs/data-producer/binary.d.ts.map +0 -1
  61. package/node/lib/fbs/data-producer/binary.js +0 -110
  62. package/node/lib/fbs/data-producer/data.d.ts +0 -10
  63. package/node/lib/fbs/data-producer/data.d.ts.map +0 -1
  64. package/node/lib/fbs/data-producer/data.js +0 -30
  65. package/node/lib/fbs/data-producer/string.d.ts +0 -22
  66. package/node/lib/fbs/data-producer/string.d.ts.map +0 -1
  67. package/node/lib/fbs/data-producer/string.js +0 -92
  68. package/node/lib/fbs/lib-uring/dump.d.ts +0 -27
  69. package/node/lib/fbs/lib-uring/dump.d.ts.map +0 -1
  70. package/node/lib/fbs/lib-uring/dump.js +0 -113
  71. package/node/lib/fbs/lib-uring.d.ts +0 -2
  72. package/node/lib/fbs/lib-uring.d.ts.map +0 -1
  73. package/node/lib/fbs/lib-uring.js +0 -8
  74. package/node/lib/fbs/message/type.d.ts +0 -7
  75. package/node/lib/fbs/message/type.d.ts.map +0 -1
  76. package/node/lib/fbs/message/type.js +0 -11
  77. package/node/lib/fbs/message-from-worker/body.d.ts +0 -12
  78. package/node/lib/fbs/message-from-worker/body.d.ts.map +0 -1
  79. package/node/lib/fbs/message-from-worker/body.js +0 -34
  80. package/node/lib/fbs/message-from-worker/message.d.ts +0 -30
  81. package/node/lib/fbs/message-from-worker/message.d.ts.map +0 -1
  82. package/node/lib/fbs/message-from-worker/message.js +0 -122
  83. package/node/lib/fbs/message-from-worker.d.ts +0 -3
  84. package/node/lib/fbs/message-from-worker.d.ts.map +0 -1
  85. package/node/lib/fbs/message-from-worker.js +0 -9
  86. package/node/lib/fbs/message-to-worker/body.d.ts +0 -10
  87. package/node/lib/fbs/message-to-worker/body.d.ts.map +0 -1
  88. package/node/lib/fbs/message-to-worker/body.js +0 -30
  89. package/node/lib/fbs/message-to-worker/message.d.ts +0 -29
  90. package/node/lib/fbs/message-to-worker/message.d.ts.map +0 -1
  91. package/node/lib/fbs/message-to-worker/message.js +0 -122
  92. package/node/lib/fbs/message-to-worker.d.ts +0 -3
  93. package/node/lib/fbs/message-to-worker.d.ts.map +0 -1
  94. package/node/lib/fbs/message-to-worker.js +0 -9
  95. package/node/lib/fbs/notification-from-worker/body.d.ts +0 -44
  96. package/node/lib/fbs/notification-from-worker/body.d.ts.map +0 -1
  97. package/node/lib/fbs/notification-from-worker/body.js +0 -98
  98. package/node/lib/fbs/notification-from-worker/event.d.ts +0 -31
  99. package/node/lib/fbs/notification-from-worker/event.d.ts.map +0 -1
  100. package/node/lib/fbs/notification-from-worker/event.js +0 -35
  101. package/node/lib/fbs/notification-from-worker/notification.d.ts +0 -52
  102. package/node/lib/fbs/notification-from-worker/notification.d.ts.map +0 -1
  103. package/node/lib/fbs/notification-from-worker/notification.js +0 -140
  104. package/node/lib/fbs/notification-from-worker.d.ts +0 -4
  105. package/node/lib/fbs/notification-from-worker.d.ts.map +0 -1
  106. package/node/lib/fbs/notification-from-worker.js +0 -11
  107. package/node/lib/fbs/notification-to-worker/body.d.ts +0 -12
  108. package/node/lib/fbs/notification-to-worker/body.d.ts.map +0 -1
  109. package/node/lib/fbs/notification-to-worker/body.js +0 -34
  110. package/node/lib/fbs/notification-to-worker/event.d.ts +0 -6
  111. package/node/lib/fbs/notification-to-worker/event.d.ts.map +0 -1
  112. package/node/lib/fbs/notification-to-worker/event.js +0 -10
  113. package/node/lib/fbs/notification-to-worker/notification.d.ts +0 -36
  114. package/node/lib/fbs/notification-to-worker/notification.d.ts.map +0 -1
  115. package/node/lib/fbs/notification-to-worker/notification.js +0 -140
  116. package/node/lib/fbs/notification-to-worker.d.ts +0 -4
  117. package/node/lib/fbs/notification-to-worker.d.ts.map +0 -1
  118. package/node/lib/fbs/notification-to-worker.js +0 -11
  119. package/node/lib/fbs/sctp-parameters/num-sctp-streams.d.ts +0 -24
  120. package/node/lib/fbs/sctp-parameters/num-sctp-streams.d.ts.map +0 -1
  121. package/node/lib/fbs/sctp-parameters/num-sctp-streams.js +0 -102
  122. package/node/lib/fbs/trace-events/fir-trace-info.d.ts +0 -21
  123. package/node/lib/fbs/trace-events/fir-trace-info.d.ts.map +0 -1
  124. package/node/lib/fbs/trace-events/fir-trace-info.js +0 -90
  125. package/node/lib/fbs/trace-events/key-frame-trace-info.d.ts +0 -25
  126. package/node/lib/fbs/trace-events/key-frame-trace-info.d.ts.map +0 -1
  127. package/node/lib/fbs/trace-events/key-frame-trace-info.js +0 -104
  128. package/node/lib/fbs/trace-events/pli-trace-info.d.ts +0 -21
  129. package/node/lib/fbs/trace-events/pli-trace-info.d.ts.map +0 -1
  130. package/node/lib/fbs/trace-events/pli-trace-info.js +0 -90
  131. package/node/lib/fbs/trace-events/rtp-trace-info.d.ts +0 -25
  132. package/node/lib/fbs/trace-events/rtp-trace-info.d.ts.map +0 -1
  133. package/node/lib/fbs/trace-events/rtp-trace-info.js +0 -104
  134. package/node/lib/fbs/trace-events/trace-event-type.d.ts +0 -8
  135. package/node/lib/fbs/trace-events/trace-event-type.d.ts.map +0 -1
  136. package/node/lib/fbs/trace-events/trace-event-type.js +0 -12
  137. package/node/lib/fbs/trace-events/trace-info.d.ts +0 -14
  138. package/node/lib/fbs/trace-events/trace-info.d.ts.map +0 -1
  139. package/node/lib/fbs/trace-events/trace-info.js +0 -38
  140. package/node/lib/fbs/trace-events.d.ts +0 -7
  141. package/node/lib/fbs/trace-events.d.ts.map +0 -1
  142. package/node/lib/fbs/trace-events.js +0 -20
  143. package/node/lib/fbs/web-rtc-server/tuple-hash.d.ts +0 -25
  144. package/node/lib/fbs/web-rtc-server/tuple-hash.d.ts.map +0 -1
  145. package/node/lib/fbs/web-rtc-server/tuple-hash.js +0 -104
@@ -23,28 +23,60 @@ namespace RTC
23
23
  TCP = 2
24
24
  };
25
25
 
26
+ class TupleKey
27
+ {
28
+ private:
29
+ friend class TransportTuple;
30
+ friend class TupleKeyHash;
31
+
32
+ public:
33
+ TupleKey() = default;
34
+ TupleKey(Protocol protocol, const void* udpSocketOrTcpConnection, const struct sockaddr* udpRemoteAddr)
35
+ : protocol(protocol),
36
+ udpSocketOrTcpConnection(udpSocketOrTcpConnection),
37
+ udpRemoteAddr(udpRemoteAddr) {};
38
+
39
+ bool operator==(const TupleKey& other) const noexcept;
40
+ bool operator!=(const TupleKey& other) const noexcept
41
+ {
42
+ return !(*this == other);
43
+ };
44
+
45
+ private:
46
+ Protocol protocol{ Protocol::UDP };
47
+ // The local endpoint is identified by object pointer identity: the
48
+ // UdpSocket or the TcpConnection. For TCP the connection alone identifies
49
+ // the whole tuple, so `udpRemoteAddr` is unused.
50
+ const void* udpSocketOrTcpConnection{ nullptr };
51
+ const struct sockaddr* udpRemoteAddr{ nullptr };
52
+ };
53
+
54
+ struct TupleKeyHash
55
+ {
56
+ size_t operator()(const TupleKey& key) const noexcept;
57
+ };
58
+
26
59
  static Protocol ProtocolFromFbs(FBS::Transport::Protocol protocol);
27
60
  static FBS::Transport::Protocol ProtocolToFbs(Protocol protocol);
28
- static uint64_t GenerateFnv1aHash(const uint8_t* data, size_t size);
29
61
 
30
62
  public:
31
63
  TransportTuple(RTC::UdpSocket* udpSocket, const struct sockaddr* udpRemoteAddr)
32
64
  : udpSocket(udpSocket),
33
65
  udpRemoteAddr(const_cast<struct sockaddr*>(udpRemoteAddr)),
34
- protocol(Protocol::UDP)
66
+ protocol(Protocol::UDP),
67
+ tupleKey(Protocol::UDP, udpSocket, udpRemoteAddr)
35
68
  {
36
- GenerateHash();
37
69
  }
38
70
 
39
71
  explicit TransportTuple(RTC::TcpConnection* tcpConnection)
40
- : tcpConnection(tcpConnection), protocol(Protocol::TCP)
72
+ : tcpConnection(tcpConnection),
73
+ protocol(Protocol::TCP),
74
+ tupleKey(Protocol::TCP, tcpConnection, nullptr)
41
75
  {
42
- GenerateHash();
43
76
  }
44
77
 
45
78
  explicit TransportTuple(const TransportTuple* tuple)
46
- : hash(tuple->hash),
47
- udpSocket(tuple->udpSocket),
79
+ : udpSocket(tuple->udpSocket),
48
80
  udpRemoteAddr(tuple->udpRemoteAddr),
49
81
  tcpConnection(tuple->tcpConnection),
50
82
  localAnnouncedAddress(tuple->localAnnouncedAddress),
@@ -54,6 +86,10 @@ namespace RTC
54
86
  {
55
87
  StoreUdpRemoteAddress();
56
88
  }
89
+ else
90
+ {
91
+ this->tupleKey = TupleKey(this->protocol, this->tcpConnection, nullptr);
92
+ }
57
93
  }
58
94
 
59
95
  public:
@@ -70,11 +106,32 @@ namespace RTC
70
106
  this->udpRemoteAddrStorage = Utils::IP::CopyAddress(this->udpRemoteAddr);
71
107
  this->udpRemoteAddr =
72
108
  reinterpret_cast<struct sockaddr*>(std::addressof(this->udpRemoteAddrStorage));
109
+ this->tupleKey = TupleKey(this->protocol, this->udpSocket, this->udpRemoteAddr);
73
110
  }
74
111
 
75
112
  bool Compare(const TransportTuple* tuple) const
76
113
  {
77
- return this->hash == tuple->hash;
114
+ if (this->protocol != tuple->protocol)
115
+ {
116
+ return false;
117
+ }
118
+
119
+ switch (this->protocol)
120
+ {
121
+ case Protocol::UDP:
122
+ {
123
+ return (
124
+ this->udpSocket == tuple->udpSocket &&
125
+ Utils::IP::CompareAddresses(this->udpRemoteAddr, tuple->udpRemoteAddr));
126
+ }
127
+
128
+ case Protocol::TCP:
129
+ {
130
+ return (this->tcpConnection == tuple->tcpConnection);
131
+ }
132
+ }
133
+
134
+ return true;
78
135
  }
79
136
 
80
137
  void SetLocalAnnouncedAddress(std::string& localAnnouncedAddress)
@@ -147,12 +204,10 @@ namespace RTC
147
204
  }
148
205
  }
149
206
 
150
- private:
151
- void SetHash();
152
- void GenerateHash();
153
-
154
- public:
155
- uint64_t hash{ 0u };
207
+ const TupleKey& GetTupleKey() const
208
+ {
209
+ return this->tupleKey;
210
+ }
156
211
 
157
212
  private:
158
213
  // Passed by argument.
@@ -163,6 +218,7 @@ namespace RTC
163
218
  // Others.
164
219
  struct sockaddr_storage udpRemoteAddrStorage{};
165
220
  Protocol protocol;
221
+ TupleKey tupleKey;
166
222
  };
167
223
  } // namespace RTC
168
224
 
@@ -10,6 +10,7 @@
10
10
  #include "RTC/UdpSocket.hpp"
11
11
  #include "RTC/WebRtcTransport.hpp"
12
12
  #include "SharedInterface.hpp"
13
+ #include "TransportTuple.hpp"
13
14
  #include <flatbuffers/flatbuffers.h>
14
15
  #include <ankerl/unordered_dense.h>
15
16
  #include <string>
@@ -118,8 +119,10 @@ namespace RTC
118
119
  ankerl::unordered_dense::set<RTC::WebRtcTransport*> webRtcTransports;
119
120
  // Map of WebRtcTransports indexed by local ICE usernameFragment.
120
121
  ankerl::unordered_dense::map<std::string, RTC::WebRtcTransport*> mapLocalIceUsernameFragmentWebRtcTransport;
121
- // Map of WebRtcTransports indexed by TransportTuple.hash.
122
- ankerl::unordered_dense::map<uint64_t, RTC::WebRtcTransport*> mapTupleWebRtcTransport;
122
+ // Map of WebRtcTransports indexed by TransportTuple::TupleKey.
123
+ ankerl::unordered_dense::
124
+ map<RTC::TransportTuple::TupleKey, RTC::WebRtcTransport*, RTC::TransportTuple::TupleKeyHash>
125
+ mapTupleWebRtcTransport;
123
126
  // Whether the destructor has been called.
124
127
  bool closing{ false };
125
128
  };
@@ -264,6 +264,12 @@ namespace Utils
264
264
 
265
265
  static void WriteRandomBytes(uint8_t* buffer, size_t len);
266
266
 
267
+ static void HashCombine(size_t& seed, size_t value)
268
+ {
269
+ // The implementation is the same as boost::hash_combine().
270
+ seed ^= value + 0x9e3779b9 + (seed << 6) + (seed >> 2);
271
+ };
272
+
267
273
  private:
268
274
  static thread_local std::mt19937_64 rng;
269
275
  static thread_local EVP_MAC* mac;
@@ -523,7 +523,8 @@ namespace RTC
523
523
  HandleTuple(
524
524
  tuple,
525
525
  request->HasAttribute(StunPacket::AttributeType::USE_CANDIDATE),
526
- request->HasAttribute(StunPacket::AttributeType::NOMINATION),
526
+ request->HasAttribute(StunPacket::AttributeType::NOMINATION) ||
527
+ request->HasAttribute(StunPacket::AttributeType::NOMINATION_OLD),
527
528
  request->GetNomination());
528
529
 
529
530
  // If state is 'connected' or 'completed' after handling the tuple, then
@@ -250,6 +250,11 @@ namespace RTC
250
250
  MS_DUMP_CLEAN(indentation + 1, " nomination: %" PRIu32, GetNomination());
251
251
  }
252
252
 
253
+ if (HasAttribute(StunPacket::AttributeType::NOMINATION_OLD))
254
+ {
255
+ MS_DUMP_CLEAN(indentation + 1, " nomination (old): %" PRIu32, GetNomination());
256
+ }
257
+
253
258
  if (HasAttribute(StunPacket::AttributeType::SOFTWARE))
254
259
  {
255
260
  const auto software = GetSoftware();
@@ -404,6 +409,8 @@ namespace RTC
404
409
 
405
410
  StoreNewAttribute(
406
411
  StunPacket::AttributeType::NOMINATION, AttributeFactoryBuffer, sizeof(nomination));
412
+ StoreNewAttribute(
413
+ StunPacket::AttributeType::NOMINATION_OLD, AttributeFactoryBuffer, sizeof(nomination));
407
414
  }
408
415
 
409
416
  void StunPacket::AddSoftware(const std::string_view software)
@@ -1058,6 +1065,7 @@ namespace RTC
1058
1065
  }
1059
1066
 
1060
1067
  case StunPacket::AttributeType::NOMINATION:
1068
+ case StunPacket::AttributeType::NOMINATION_OLD:
1061
1069
  {
1062
1070
  if (attrLen != 4)
1063
1071
  {
@@ -16,7 +16,7 @@ namespace RTC
16
16
 
17
17
  /* Instance methods. */
18
18
 
19
- NackGenerator::NackGenerator(Listener* listener, SharedInterface* shared, unsigned int sendNackDelayMs)
19
+ NackGenerator::NackGenerator(Listener* listener, SharedInterface* shared, uint32_t sendNackDelayMs)
20
20
  : listener(listener),
21
21
  shared(shared),
22
22
  sendNackDelayMs(sendNackDelayMs),
@@ -797,11 +797,6 @@ namespace RTC
797
797
  const auto protocolBits = static_cast<uint8_t>(key.protocol);
798
798
  const auto familyBits = static_cast<uint16_t>(key.bindAddr.ss_family);
799
799
 
800
- auto hashCombine = [](size_t& seed, size_t value)
801
- {
802
- seed ^= value + 0x9e3779b9 + (seed << 6) + (seed >> 2);
803
- };
804
-
805
800
  size_t seed = 0;
806
801
 
807
802
  switch (key.bindAddr.ss_family)
@@ -810,11 +805,12 @@ namespace RTC
810
805
  {
811
806
  const auto* in = reinterpret_cast<const sockaddr_in*>(std::addressof(key.bindAddr));
812
807
 
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));
808
+ Utils::Crypto::HashCombine(seed, ankerl::unordered_dense::hash<uint8_t>{}(protocolBits));
809
+ Utils::Crypto::HashCombine(seed, ankerl::unordered_dense::hash<uint16_t>{}(familyBits));
810
+ Utils::Crypto::HashCombine(
811
+ seed, ankerl::unordered_dense::hash<uint32_t>{}(in->sin_addr.s_addr));
812
+ Utils::Crypto::HashCombine(seed, ankerl::unordered_dense::hash<uint16_t>{}(key.minPort));
813
+ Utils::Crypto::HashCombine(seed, ankerl::unordered_dense::hash<uint16_t>{}(key.maxPort));
818
814
 
819
815
  break;
820
816
  }
@@ -830,22 +826,22 @@ namespace RTC
830
826
  std::memcpy(std::addressof(hi), addr, sizeof(uint64_t));
831
827
  std::memcpy(std::addressof(lo), addr + sizeof(uint64_t), sizeof(uint64_t));
832
828
 
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));
829
+ Utils::Crypto::HashCombine(seed, ankerl::unordered_dense::hash<uint8_t>{}(protocolBits));
830
+ Utils::Crypto::HashCombine(seed, ankerl::unordered_dense::hash<uint16_t>{}(familyBits));
831
+ Utils::Crypto::HashCombine(seed, ankerl::unordered_dense::hash<uint64_t>{}(hi));
832
+ Utils::Crypto::HashCombine(seed, ankerl::unordered_dense::hash<uint64_t>{}(lo));
833
+ Utils::Crypto::HashCombine(seed, ankerl::unordered_dense::hash<uint16_t>{}(key.minPort));
834
+ Utils::Crypto::HashCombine(seed, ankerl::unordered_dense::hash<uint16_t>{}(key.maxPort));
839
835
 
840
836
  break;
841
837
  }
842
838
 
843
839
  default:
844
840
  {
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));
841
+ Utils::Crypto::HashCombine(seed, ankerl::unordered_dense::hash<uint8_t>{}(protocolBits));
842
+ Utils::Crypto::HashCombine(seed, ankerl::unordered_dense::hash<uint16_t>{}(familyBits));
843
+ Utils::Crypto::HashCombine(seed, ankerl::unordered_dense::hash<uint16_t>{}(key.minPort));
844
+ Utils::Crypto::HashCombine(seed, ankerl::unordered_dense::hash<uint16_t>{}(key.maxPort));
849
845
 
850
846
  break;
851
847
  }
@@ -20,7 +20,7 @@ namespace RTC
20
20
 
21
21
  static constexpr size_t ProducerSendBufferSize{ 65536 };
22
22
  static thread_local uint8_t ProducerSendBuffer[ProducerSendBufferSize];
23
- static constexpr unsigned int SendNackDelay{ 10u }; // In ms.
23
+ static constexpr uint32_t SendNackDelay{ 10u }; // In ms.
24
24
 
25
25
  /* Instance methods. */
26
26
 
@@ -140,9 +140,7 @@ namespace RTC
140
140
  }
141
141
 
142
142
  // There are dropped inputs, calculate 'base' for this input.
143
- auto droppedCount = std::distance(
144
- this->dropped.begin(),
145
- std::lower_bound(this->dropped.begin(), this->dropped.end(), input, SeqLowerThan()));
143
+ auto droppedCount = std::distance(this->dropped.begin(), it);
146
144
 
147
145
  base = (this->base - droppedCount) & SeqManager::MaxValue;
148
146
  }
@@ -187,7 +185,10 @@ namespace RTC
187
185
  template<typename T, uint8_t N>
188
186
  T SeqManager<T, N>::GetMaxOutput() const
189
187
  {
190
- return this->maxOutput;
188
+ // 'maxOutput' is stored in the offset-less space (as 'base' and comparisons
189
+ // use it), so apply 'initialOutput' here, just like `Input()` does before
190
+ // returning the output to the caller.
191
+ return (this->maxOutput + this->initialOutput) & SeqManager::MaxValue;
191
192
  }
192
193
 
193
194
  /*
@@ -49,22 +49,6 @@ namespace RTC
49
49
  }
50
50
  }
51
51
 
52
- uint64_t TransportTuple::GenerateFnv1aHash(const uint8_t* data, size_t size)
53
- {
54
- MS_TRACE();
55
-
56
- const uint64_t fnvOffsetBasis = 14695981039346656037ull;
57
- const uint64_t fnvPrime = 1099511628211ull;
58
- uint64_t hash = fnvOffsetBasis;
59
-
60
- for (size_t i = 0; i < size; ++i)
61
- {
62
- hash = (hash ^ data[i]) * fnvPrime;
63
- }
64
-
65
- return hash;
66
- }
67
-
68
52
  /* Instance methods. */
69
53
 
70
54
  void TransportTuple::CloseTcpConnection()
@@ -143,54 +127,107 @@ namespace RTC
143
127
  }
144
128
  }
145
129
 
146
- MS_DUMP_CLEAN(indentation, " hash: %" PRIu64, this->hash);
147
-
148
130
  MS_DUMP_CLEAN(indentation, "</TransportTuple>");
149
131
  }
150
132
 
151
- void TransportTuple::GenerateHash()
133
+ bool TransportTuple::TupleKey::operator==(const TupleKey& other) const noexcept
152
134
  {
153
135
  MS_TRACE();
154
136
 
155
- const auto* localSockAddr = GetLocalAddress();
156
- const auto* remoteSockAddr = GetRemoteAddress();
157
-
158
- // Maximum buffer length for two IPv6 addresses and ports plus protocol.
159
- static constexpr size_t BufferSize = ((16 + 2) * 2) + 1;
160
- uint8_t buffer[BufferSize] = {};
161
- size_t idx = 0;
137
+ if (this->protocol != other.protocol)
138
+ {
139
+ return false;
140
+ }
162
141
 
163
- auto appendSockAddr = [&](const struct sockaddr* addr)
142
+ switch (this->protocol)
164
143
  {
165
- if (addr->sa_family == AF_INET)
144
+ // For UDP compare the remote address first (it discriminates faster) and then
145
+ // the socket.
146
+ case Protocol::UDP:
166
147
  {
167
- const auto* in = reinterpret_cast<const struct sockaddr_in*>(addr);
168
- const auto* ip = reinterpret_cast<const uint8_t*>(&in->sin_addr.s_addr);
169
- const uint16_t port = ntohs(in->sin_port);
170
-
171
- std::memcpy(buffer + idx, ip, 4);
172
- idx += 4;
173
- buffer[idx++] = (port >> 8) & 0xFF;
174
- buffer[idx++] = port & 0xFF;
148
+ return Utils::IP::CompareAddresses(this->udpRemoteAddr, other.udpRemoteAddr) &&
149
+ this->udpSocketOrTcpConnection == other.udpSocketOrTcpConnection;
175
150
  }
176
- else if (addr->sa_family == AF_INET6)
151
+
152
+ // For TCP the connection pointer fully identifies the tuple.
153
+ case Protocol::TCP:
177
154
  {
178
- const auto* in6 = reinterpret_cast<const struct sockaddr_in6*>(addr);
179
- const auto* ip = reinterpret_cast<const uint8_t*>(&in6->sin6_addr);
180
- const uint16_t port = ntohs(in6->sin6_port);
181
-
182
- std::memcpy(buffer + idx, ip, 16);
183
- idx += 16;
184
- buffer[idx++] = (port >> 8) & 0xFF;
185
- buffer[idx++] = port & 0xFF;
155
+ return this->udpSocketOrTcpConnection == other.udpSocketOrTcpConnection;
186
156
  }
187
- };
188
157
 
189
- appendSockAddr(localSockAddr);
190
- appendSockAddr(remoteSockAddr);
158
+ NO_DEFAULT_GCC();
159
+ }
160
+ }
161
+
162
+ size_t TransportTuple::TupleKeyHash::operator()(const TupleKey& key) const noexcept
163
+ {
164
+ MS_TRACE();
165
+
166
+ const auto protocolBits = static_cast<uint8_t>(key.protocol);
191
167
 
192
- buffer[idx] = static_cast<uint8_t>(this->protocol);
168
+ size_t seed = 0;
193
169
 
194
- this->hash = TransportTuple::GenerateFnv1aHash(buffer, idx + 1);
170
+ Utils::Crypto::HashCombine(seed, ankerl::unordered_dense::hash<uint8_t>{}(protocolBits));
171
+ Utils::Crypto::HashCombine(
172
+ seed,
173
+ ankerl::unordered_dense::hash<uintptr_t>{}(
174
+ reinterpret_cast<uintptr_t>(key.udpSocketOrTcpConnection)));
175
+
176
+ switch (key.protocol)
177
+ {
178
+ case Protocol::UDP:
179
+ {
180
+ // For UDP also combine the remote address.
181
+ const auto familyBits = static_cast<uint16_t>(key.udpRemoteAddr->sa_family);
182
+
183
+ Utils::Crypto::HashCombine(seed, ankerl::unordered_dense::hash<uint16_t>{}(familyBits));
184
+
185
+ switch (key.udpRemoteAddr->sa_family)
186
+ {
187
+ case AF_INET:
188
+ {
189
+ const auto* remoteIn = reinterpret_cast<const sockaddr_in*>(key.udpRemoteAddr);
190
+
191
+ Utils::Crypto::HashCombine(
192
+ seed, ankerl::unordered_dense::hash<uint32_t>{}(remoteIn->sin_addr.s_addr));
193
+ Utils::Crypto::HashCombine(
194
+ seed, ankerl::unordered_dense::hash<uint16_t>{}(remoteIn->sin_port));
195
+
196
+ break;
197
+ }
198
+
199
+ case AF_INET6:
200
+ {
201
+ const auto* remoteIn6 = reinterpret_cast<const sockaddr_in6*>(key.udpRemoteAddr);
202
+ const auto* addr = remoteIn6->sin6_addr.s6_addr;
203
+
204
+ uint64_t hi;
205
+ uint64_t lo;
206
+
207
+ std::memcpy(std::addressof(hi), addr, sizeof(uint64_t));
208
+ std::memcpy(std::addressof(lo), addr + sizeof(uint64_t), sizeof(uint64_t));
209
+
210
+ Utils::Crypto::HashCombine(seed, ankerl::unordered_dense::hash<uint64_t>{}(hi));
211
+ Utils::Crypto::HashCombine(seed, ankerl::unordered_dense::hash<uint64_t>{}(lo));
212
+ Utils::Crypto::HashCombine(
213
+ seed, ankerl::unordered_dense::hash<uint16_t>{}(remoteIn6->sin6_port));
214
+
215
+ break;
216
+ }
217
+
218
+ default:;
219
+ }
220
+
221
+ return seed;
222
+ }
223
+
224
+ case Protocol::TCP:
225
+ {
226
+ // For TCP the connection pointer is enough.
227
+ return seed;
228
+ }
229
+
230
+ NO_DEFAULT_GCC();
231
+ }
195
232
  }
196
233
  } // namespace RTC
@@ -303,26 +303,13 @@ namespace RTC
303
303
  builder, localIceUsernameFragment.c_str(), webRtcTransport->id.c_str()));
304
304
  }
305
305
 
306
- // Add tupleHashes.
307
- std::vector<flatbuffers::Offset<FBS::WebRtcServer::TupleHash>> tupleHashes;
308
-
309
- for (const auto& kv : this->mapTupleWebRtcTransport)
310
- {
311
- const auto& tupleHash = kv.first;
312
- const auto* webRtcTransport = kv.second;
313
-
314
- tupleHashes.emplace_back(
315
- FBS::WebRtcServer::CreateTupleHashDirect(builder, tupleHash, webRtcTransport->id.c_str()));
316
- }
317
-
318
306
  return FBS::WebRtcServer::CreateDumpResponseDirect(
319
307
  builder,
320
308
  this->id.c_str(),
321
- &udpSockets,
322
- &tcpServers,
323
- &webRtcTransportIds,
324
- &localIceUsernameFragments,
325
- &tupleHashes);
309
+ std::addressof(udpSockets),
310
+ std::addressof(tcpServers),
311
+ std::addressof(webRtcTransportIds),
312
+ std::addressof(localIceUsernameFragments));
326
313
  }
327
314
 
328
315
  void WebRtcServer::HandleRequest(Channel::ChannelRequest* request)
@@ -450,7 +437,7 @@ namespace RTC
450
437
  }
451
438
 
452
439
  // First try doing lookup in the tuples table.
453
- auto it1 = this->mapTupleWebRtcTransport.find(tuple->hash);
440
+ auto it1 = this->mapTupleWebRtcTransport.find(tuple->GetTupleKey());
454
441
 
455
442
  if (it1 != this->mapTupleWebRtcTransport.end())
456
443
  {
@@ -488,7 +475,7 @@ namespace RTC
488
475
  {
489
476
  MS_TRACE();
490
477
 
491
- auto it = this->mapTupleWebRtcTransport.find(tuple->hash);
478
+ auto it = this->mapTupleWebRtcTransport.find(tuple->GetTupleKey());
492
479
 
493
480
  if (it == this->mapTupleWebRtcTransport.end())
494
481
  {
@@ -562,14 +549,16 @@ namespace RTC
562
549
  {
563
550
  MS_TRACE();
564
551
 
565
- if (this->mapTupleWebRtcTransport.find(tuple->hash) != this->mapTupleWebRtcTransport.end())
552
+ auto tupleKey = tuple->GetTupleKey();
553
+
554
+ if (this->mapTupleWebRtcTransport.contains(tupleKey))
566
555
  {
567
- MS_WARN_TAG(ice, "tuple hash already exists in the table");
556
+ MS_WARN_TAG(ice, "tuple key already exists in the table");
568
557
 
569
558
  return;
570
559
  }
571
560
 
572
- this->mapTupleWebRtcTransport[tuple->hash] = webRtcTransport;
561
+ this->mapTupleWebRtcTransport[tupleKey] = webRtcTransport;
573
562
  }
574
563
 
575
564
  inline void WebRtcServer::OnWebRtcTransportTransportTupleRemoved(
@@ -577,14 +566,16 @@ namespace RTC
577
566
  {
578
567
  MS_TRACE();
579
568
 
580
- if (this->mapTupleWebRtcTransport.find(tuple->hash) == this->mapTupleWebRtcTransport.end())
569
+ auto it = this->mapTupleWebRtcTransport.find(tuple->GetTupleKey());
570
+
571
+ if (it == this->mapTupleWebRtcTransport.end())
581
572
  {
582
- MS_DEBUG_TAG(ice, "tuple hash not found in the table");
573
+ MS_DEBUG_TAG(ice, "tuple key not found in the table");
583
574
 
584
575
  return;
585
576
  }
586
577
 
587
- this->mapTupleWebRtcTransport.erase(tuple->hash);
578
+ this->mapTupleWebRtcTransport.erase(it);
588
579
  }
589
580
 
590
581
  inline void WebRtcServer::OnUdpSocketPacketReceived(
@@ -598,7 +589,7 @@ namespace RTC
598
589
 
599
590
  RTC::TransportTuple tuple(socket, remoteAddr);
600
591
 
601
- OnPacketReceived(&tuple, data, len, bufferLen);
592
+ OnPacketReceived(std::addressof(tuple), data, len, bufferLen);
602
593
  }
603
594
 
604
595
  inline void WebRtcServer::OnRtcTcpConnectionClosed(
@@ -612,7 +603,7 @@ namespace RTC
612
603
  // mapTupleWebRtcTransport because this event may be called after the tuple
613
604
  // was removed from it.
614
605
 
615
- auto it = this->mapTupleWebRtcTransport.find(tuple.hash);
606
+ auto it = this->mapTupleWebRtcTransport.find(tuple.GetTupleKey());
616
607
 
617
608
  if (it == this->mapTupleWebRtcTransport.end())
618
609
  {
@@ -621,7 +612,7 @@ namespace RTC
621
612
 
622
613
  auto* webRtcTransport = it->second;
623
614
 
624
- webRtcTransport->RemoveTuple(&tuple);
615
+ webRtcTransport->RemoveTuple(std::addressof(tuple));
625
616
  }
626
617
 
627
618
  inline void WebRtcServer::OnTcpConnectionPacketReceived(
@@ -631,6 +622,6 @@ namespace RTC
631
622
 
632
623
  RTC::TransportTuple tuple(connection);
633
624
 
634
- OnPacketReceived(&tuple, data, len, bufferLen);
625
+ OnPacketReceived(std::addressof(tuple), data, len, bufferLen);
635
626
  }
636
627
  } // namespace RTC
@@ -508,7 +508,9 @@ SCENARIO("ICE StunPacket", "[serializable][ice][stunpacket]")
508
508
  // Byte length: 8.
509
509
  uint64_t iceControlling = 15697499370457501716u;
510
510
  // Byte length of USE_CANDIDATE: 0.
511
- // // Byte length: 4.
511
+ // NOTE: `AddNomination()` adds the "NOMINATION" attribute with both the old
512
+ // and the new value, so it will insert 2 attributes instead of one.
513
+ // Byte length: 4 x 2.
512
514
  uint32_t nomination = 12345678u;
513
515
  // Byte length: 18 (2 byte of padding needed).
514
516
  std::string software = "mediasoup x.y.z :)";
@@ -518,7 +520,7 @@ SCENARIO("ICE StunPacket", "[serializable][ice][stunpacket]")
518
520
 
519
521
  // Total length of the attributes.
520
522
  size_t attributesLen =
521
- (4 + 27 + 1) + (4 + 4) + (4 + 8) + (4) + (4 + 4) + (4 + 18 + 2) + (4 + 4 + 23 + 1);
523
+ (4 + 27 + 1) + (4 + 4) + (4 + 8) + (4) + ((4 + 4) * 2) + (4 + 18 + 2) + (4 + 4 + 23 + 1);
522
524
 
523
525
  request->AddUsername(username);
524
526
  request->AddPriority(priority);
@@ -533,6 +535,8 @@ SCENARIO("ICE StunPacket", "[serializable][ice][stunpacket]")
533
535
  REQUIRE_THROWS_AS(request->AddPriority(priority), MediaSoupError);
534
536
  REQUIRE_THROWS_AS(request->AddIceControlling(iceControlling), MediaSoupError);
535
537
  REQUIRE_THROWS_AS(request->AddUseCandidate(), MediaSoupError);
538
+ // NOTE: `AddNomination()` adds the "NOMINATION" attribute with both the old
539
+ // and the new value, so it will insert 2 attributes instead of one.
536
540
  REQUIRE_THROWS_AS(request->AddNomination(nomination), MediaSoupError);
537
541
  REQUIRE_THROWS_AS(request->AddSoftware(software), MediaSoupError);
538
542
  REQUIRE_THROWS_AS(request->AddErrorCode(errorCode, errorReasonPhrase), MediaSoupError);
@@ -8,7 +8,7 @@
8
8
 
9
9
  // 17: 16 bit mask + the initial sequence number.
10
10
  static constexpr size_t MaxRequestedPackets{ 17 };
11
- static constexpr unsigned int SendNackDelay{ 0u }; // In ms.
11
+ static constexpr uint32_t SendNackDelay{ 0u }; // In ms.
12
12
  static const bool UseRtpInactivityCheck{ false };
13
13
 
14
14
  SCENARIO("RtpStreamRecv", "[rtp][rtpstream][rtpstreamrecv]")
@@ -9,7 +9,7 @@
9
9
 
10
10
  SCENARIO("NackGenerator generator", "[rtp][rtcp][nack]")
11
11
  {
12
- constexpr unsigned int SendNackDelay{ 0u }; // In ms.
12
+ constexpr uint32_t SendNackDelay{ 0u }; // In ms.
13
13
 
14
14
  struct TestNackGeneratorInput
15
15
  {