mediasoup 3.19.21 → 3.20.0

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 (649) hide show
  1. package/node/lib/ActiveSpeakerObserver.js +34 -1
  2. package/node/lib/AudioLevelObserver.js +35 -2
  3. package/node/lib/Channel.d.ts.map +1 -1
  4. package/node/lib/Channel.js +37 -5
  5. package/node/lib/Consumer.js +39 -6
  6. package/node/lib/DataConsumer.d.ts.map +1 -1
  7. package/node/lib/DataConsumer.js +39 -5
  8. package/node/lib/DataConsumerTypes.d.ts +1 -0
  9. package/node/lib/DataConsumerTypes.d.ts.map +1 -1
  10. package/node/lib/DataProducer.js +37 -4
  11. package/node/lib/DirectTransport.js +37 -4
  12. package/node/lib/DirectTransportTypes.d.ts +7 -2
  13. package/node/lib/DirectTransportTypes.d.ts.map +1 -1
  14. package/node/lib/Logger.js +4 -1
  15. package/node/lib/PipeTransport.d.ts +3 -1
  16. package/node/lib/PipeTransport.d.ts.map +1 -1
  17. package/node/lib/PipeTransport.js +56 -5
  18. package/node/lib/PipeTransportTypes.d.ts +28 -8
  19. package/node/lib/PipeTransportTypes.d.ts.map +1 -1
  20. package/node/lib/PlainTransport.d.ts +3 -1
  21. package/node/lib/PlainTransport.d.ts.map +1 -1
  22. package/node/lib/PlainTransport.js +54 -3
  23. package/node/lib/PlainTransportTypes.d.ts +27 -7
  24. package/node/lib/PlainTransportTypes.d.ts.map +1 -1
  25. package/node/lib/Producer.js +40 -7
  26. package/node/lib/Router.d.ts +5 -5
  27. package/node/lib/Router.d.ts.map +1 -1
  28. package/node/lib/Router.js +81 -36
  29. package/node/lib/RouterTypes.d.ts +25 -3
  30. package/node/lib/RouterTypes.d.ts.map +1 -1
  31. package/node/lib/RtpObserver.js +36 -3
  32. package/node/lib/Transport.d.ts +3 -1
  33. package/node/lib/Transport.d.ts.map +1 -1
  34. package/node/lib/Transport.js +74 -22
  35. package/node/lib/TransportTypes.d.ts +2 -1
  36. package/node/lib/TransportTypes.d.ts.map +1 -1
  37. package/node/lib/WebRtcServer.js +36 -3
  38. package/node/lib/WebRtcTransport.d.ts +3 -1
  39. package/node/lib/WebRtcTransport.d.ts.map +1 -1
  40. package/node/lib/WebRtcTransport.js +55 -4
  41. package/node/lib/WebRtcTransportTypes.d.ts +27 -7
  42. package/node/lib/WebRtcTransportTypes.d.ts.map +1 -1
  43. package/node/lib/Worker.d.ts +2 -1
  44. package/node/lib/Worker.d.ts.map +1 -1
  45. package/node/lib/Worker.js +71 -25
  46. package/node/lib/WorkerTypes.d.ts +0 -4
  47. package/node/lib/WorkerTypes.d.ts.map +1 -1
  48. package/node/lib/enhancedEvents.d.ts +2 -2
  49. package/node/lib/enhancedEvents.d.ts.map +1 -1
  50. package/node/lib/enhancedEvents.js +0 -2
  51. package/node/lib/fbs/active-speaker-observer/active-speaker-observer-options.js +34 -1
  52. package/node/lib/fbs/active-speaker-observer/dominant-speaker-notification.js +34 -1
  53. package/node/lib/fbs/audio-level-observer/audio-level-observer-options.js +34 -1
  54. package/node/lib/fbs/audio-level-observer/volume.js +34 -1
  55. package/node/lib/fbs/audio-level-observer/volumes-notification.js +34 -1
  56. package/node/lib/fbs/common/string-string-array.js +34 -1
  57. package/node/lib/fbs/common/string-string.js +34 -1
  58. package/node/lib/fbs/common/string-uint8.js +34 -1
  59. package/node/lib/fbs/common/uint16-string.js +34 -1
  60. package/node/lib/fbs/common/uint32-string.js +34 -1
  61. package/node/lib/fbs/consumer/base-consumer-dump.js +34 -1
  62. package/node/lib/fbs/consumer/consumer-dump.js +34 -1
  63. package/node/lib/fbs/consumer/consumer-layers.js +34 -1
  64. package/node/lib/fbs/consumer/consumer-score.js +34 -1
  65. package/node/lib/fbs/consumer/dump-response.js +34 -1
  66. package/node/lib/fbs/consumer/enable-trace-event-request.js +34 -1
  67. package/node/lib/fbs/consumer/fir-trace-info.js +34 -1
  68. package/node/lib/fbs/consumer/get-stats-response.js +34 -1
  69. package/node/lib/fbs/consumer/key-frame-trace-info.js +34 -1
  70. package/node/lib/fbs/consumer/layers-change-notification.js +34 -1
  71. package/node/lib/fbs/consumer/pli-trace-info.js +34 -1
  72. package/node/lib/fbs/consumer/rtp-notification.js +34 -1
  73. package/node/lib/fbs/consumer/rtp-trace-info.js +34 -1
  74. package/node/lib/fbs/consumer/score-notification.js +34 -1
  75. package/node/lib/fbs/consumer/set-preferred-layers-request.js +34 -1
  76. package/node/lib/fbs/consumer/set-preferred-layers-response.js +34 -1
  77. package/node/lib/fbs/consumer/set-priority-request.js +34 -1
  78. package/node/lib/fbs/consumer/set-priority-response.js +34 -1
  79. package/node/lib/fbs/consumer/trace-notification.js +34 -1
  80. package/node/lib/fbs/data-consumer/add-subchannel-request.js +34 -1
  81. package/node/lib/fbs/data-consumer/add-subchannel-response.js +34 -1
  82. package/node/lib/fbs/data-consumer/buffered-amount-low-notification.js +34 -1
  83. package/node/lib/fbs/data-consumer/dump-response.d.ts +5 -2
  84. package/node/lib/fbs/data-consumer/dump-response.d.ts.map +1 -1
  85. package/node/lib/fbs/data-consumer/dump-response.js +60 -16
  86. package/node/lib/fbs/data-consumer/get-buffered-amount-response.js +34 -1
  87. package/node/lib/fbs/data-consumer/get-stats-response.js +34 -1
  88. package/node/lib/fbs/data-consumer/message-notification.js +34 -1
  89. package/node/lib/fbs/data-consumer/remove-subchannel-request.js +34 -1
  90. package/node/lib/fbs/data-consumer/remove-subchannel-response.js +34 -1
  91. package/node/lib/fbs/data-consumer/send-request.js +34 -1
  92. package/node/lib/fbs/data-consumer/set-buffered-amount-low-threshold-request.js +34 -1
  93. package/node/lib/fbs/data-consumer/set-subchannels-request.js +34 -1
  94. package/node/lib/fbs/data-consumer/set-subchannels-response.js +34 -1
  95. package/node/lib/fbs/data-consumer/type.d.ts +5 -0
  96. package/node/lib/fbs/data-consumer/type.d.ts.map +1 -0
  97. package/node/lib/fbs/data-consumer/type.js +10 -0
  98. package/node/lib/fbs/data-consumer.d.ts +1 -0
  99. package/node/lib/fbs/data-consumer.d.ts.map +1 -1
  100. package/node/lib/fbs/data-consumer.js +3 -1
  101. package/node/lib/fbs/data-producer/dump-response.js +34 -1
  102. package/node/lib/fbs/data-producer/get-stats-response.js +34 -1
  103. package/node/lib/fbs/data-producer/send-notification.js +34 -1
  104. package/node/lib/fbs/direct-transport/direct-transport-options.js +34 -1
  105. package/node/lib/fbs/direct-transport/dump-response.js +34 -1
  106. package/node/lib/fbs/direct-transport/get-stats-response.js +34 -1
  107. package/node/lib/fbs/direct-transport/rtcp-notification.js +34 -1
  108. package/node/lib/fbs/lib-uring/dump.js +34 -1
  109. package/node/lib/fbs/log/log.js +34 -1
  110. package/node/lib/fbs/message/message.js +34 -1
  111. package/node/lib/fbs/notification/body.d.ts +24 -22
  112. package/node/lib/fbs/notification/body.d.ts.map +1 -1
  113. package/node/lib/fbs/notification/body.js +24 -20
  114. package/node/lib/fbs/notification/event.d.ts +27 -26
  115. package/node/lib/fbs/notification/event.d.ts.map +1 -1
  116. package/node/lib/fbs/notification/event.js +27 -26
  117. package/node/lib/fbs/notification/notification.d.ts +3 -2
  118. package/node/lib/fbs/notification/notification.d.ts.map +1 -1
  119. package/node/lib/fbs/notification/notification.js +34 -1
  120. package/node/lib/fbs/pipe-transport/connect-request.js +34 -1
  121. package/node/lib/fbs/pipe-transport/connect-response.js +34 -1
  122. package/node/lib/fbs/pipe-transport/dump-response.js +34 -1
  123. package/node/lib/fbs/pipe-transport/get-stats-response.js +34 -1
  124. package/node/lib/fbs/pipe-transport/pipe-transport-options.js +34 -1
  125. package/node/lib/fbs/plain-transport/connect-request.js +34 -1
  126. package/node/lib/fbs/plain-transport/connect-response.js +34 -1
  127. package/node/lib/fbs/plain-transport/dump-response.js +34 -1
  128. package/node/lib/fbs/plain-transport/get-stats-response.js +34 -1
  129. package/node/lib/fbs/plain-transport/plain-transport-options.js +34 -1
  130. package/node/lib/fbs/plain-transport/rtcp-tuple-notification.js +34 -1
  131. package/node/lib/fbs/plain-transport/tuple-notification.js +34 -1
  132. package/node/lib/fbs/producer/dump-response.js +34 -1
  133. package/node/lib/fbs/producer/enable-trace-event-request.js +34 -1
  134. package/node/lib/fbs/producer/fir-trace-info.js +34 -1
  135. package/node/lib/fbs/producer/get-stats-response.js +34 -1
  136. package/node/lib/fbs/producer/key-frame-trace-info.js +34 -1
  137. package/node/lib/fbs/producer/pli-trace-info.js +34 -1
  138. package/node/lib/fbs/producer/rtp-trace-info.js +34 -1
  139. package/node/lib/fbs/producer/score-notification.js +34 -1
  140. package/node/lib/fbs/producer/score.js +34 -1
  141. package/node/lib/fbs/producer/send-notification.js +34 -1
  142. package/node/lib/fbs/producer/sr-trace-info.js +34 -1
  143. package/node/lib/fbs/producer/trace-notification.js +34 -1
  144. package/node/lib/fbs/producer/video-orientation-change-notification.js +34 -1
  145. package/node/lib/fbs/request/request.js +34 -1
  146. package/node/lib/fbs/response/response.js +34 -1
  147. package/node/lib/fbs/router/close-rtp-observer-request.js +34 -1
  148. package/node/lib/fbs/router/close-transport-request.js +34 -1
  149. package/node/lib/fbs/router/create-active-speaker-observer-request.js +34 -1
  150. package/node/lib/fbs/router/create-audio-level-observer-request.js +34 -1
  151. package/node/lib/fbs/router/create-direct-transport-request.js +34 -1
  152. package/node/lib/fbs/router/create-pipe-transport-request.js +34 -1
  153. package/node/lib/fbs/router/create-plain-transport-request.js +34 -1
  154. package/node/lib/fbs/router/create-web-rtc-transport-request.js +34 -1
  155. package/node/lib/fbs/router/dump-response.js +34 -1
  156. package/node/lib/fbs/rtp-observer/add-producer-request.js +34 -1
  157. package/node/lib/fbs/rtp-observer/remove-producer-request.js +34 -1
  158. package/node/lib/fbs/rtp-packet/dump.js +34 -1
  159. package/node/lib/fbs/rtp-parameters/boolean.js +34 -1
  160. package/node/lib/fbs/rtp-parameters/codec-mapping.js +34 -1
  161. package/node/lib/fbs/rtp-parameters/double.js +34 -1
  162. package/node/lib/fbs/rtp-parameters/encoding-mapping.js +34 -1
  163. package/node/lib/fbs/rtp-parameters/integer32-array.js +34 -1
  164. package/node/lib/fbs/rtp-parameters/integer32.js +34 -1
  165. package/node/lib/fbs/rtp-parameters/parameter.js +34 -1
  166. package/node/lib/fbs/rtp-parameters/rtcp-feedback.js +34 -1
  167. package/node/lib/fbs/rtp-parameters/rtcp-parameters.js +34 -1
  168. package/node/lib/fbs/rtp-parameters/rtp-codec-parameters.js +34 -1
  169. package/node/lib/fbs/rtp-parameters/rtp-encoding-parameters.js +34 -1
  170. package/node/lib/fbs/rtp-parameters/rtp-header-extension-parameters.js +34 -1
  171. package/node/lib/fbs/rtp-parameters/rtp-mapping.js +34 -1
  172. package/node/lib/fbs/rtp-parameters/rtp-parameters.js +34 -1
  173. package/node/lib/fbs/rtp-parameters/rtx.js +34 -1
  174. package/node/lib/fbs/rtp-parameters/string.js +34 -1
  175. package/node/lib/fbs/rtp-stream/base-stats.js +34 -1
  176. package/node/lib/fbs/rtp-stream/bitrate-by-layer.js +34 -1
  177. package/node/lib/fbs/rtp-stream/dump.js +34 -1
  178. package/node/lib/fbs/rtp-stream/params.js +34 -1
  179. package/node/lib/fbs/rtp-stream/recv-stats.js +34 -1
  180. package/node/lib/fbs/rtp-stream/send-stats.js +34 -1
  181. package/node/lib/fbs/rtp-stream/stats.js +34 -1
  182. package/node/lib/fbs/rtx-stream/params.js +34 -1
  183. package/node/lib/fbs/rtx-stream/rtx-dump.js +34 -1
  184. package/node/lib/fbs/sctp-association/sctp-negotiated-capabilities.d.ts +24 -0
  185. package/node/lib/fbs/sctp-association/sctp-negotiated-capabilities.d.ts.map +1 -0
  186. package/node/lib/fbs/sctp-association/sctp-negotiated-capabilities.js +102 -0
  187. package/node/lib/fbs/sctp-association.d.ts +1 -0
  188. package/node/lib/fbs/sctp-association.d.ts.map +1 -1
  189. package/node/lib/fbs/sctp-association.js +4 -1
  190. package/node/lib/fbs/sctp-parameters/num-sctp-streams.js +34 -1
  191. package/node/lib/fbs/sctp-parameters/sctp-parameters.d.ts +14 -14
  192. package/node/lib/fbs/sctp-parameters/sctp-parameters.d.ts.map +1 -1
  193. package/node/lib/fbs/sctp-parameters/sctp-parameters.js +73 -40
  194. package/node/lib/fbs/sctp-parameters/sctp-stream-parameters.js +34 -1
  195. package/node/lib/fbs/sctp-parameters.d.ts +0 -1
  196. package/node/lib/fbs/sctp-parameters.d.ts.map +1 -1
  197. package/node/lib/fbs/sctp-parameters.js +1 -4
  198. package/node/lib/fbs/srtp-parameters/srtp-parameters.js +34 -1
  199. package/node/lib/fbs/transport/bwe-trace-info.js +34 -1
  200. package/node/lib/fbs/transport/close-consumer-request.js +34 -1
  201. package/node/lib/fbs/transport/close-data-consumer-request.js +34 -1
  202. package/node/lib/fbs/transport/close-data-producer-request.js +34 -1
  203. package/node/lib/fbs/transport/close-producer-request.js +34 -1
  204. package/node/lib/fbs/transport/consume-data-request.d.ts +1 -1
  205. package/node/lib/fbs/transport/consume-data-request.js +35 -2
  206. package/node/lib/fbs/transport/consume-request.js +34 -1
  207. package/node/lib/fbs/transport/consume-response.js +34 -1
  208. package/node/lib/fbs/transport/dump.d.ts +7 -4
  209. package/node/lib/fbs/transport/dump.d.ts.map +1 -1
  210. package/node/lib/fbs/transport/dump.js +66 -22
  211. package/node/lib/fbs/transport/enable-trace-event-request.js +34 -1
  212. package/node/lib/fbs/transport/listen-info.js +34 -1
  213. package/node/lib/fbs/transport/options.d.ts +14 -14
  214. package/node/lib/fbs/transport/options.d.ts.map +1 -1
  215. package/node/lib/fbs/transport/options.js +92 -51
  216. package/node/lib/fbs/transport/port-range.js +34 -1
  217. package/node/lib/fbs/transport/produce-data-request.js +34 -1
  218. package/node/lib/fbs/transport/produce-request.js +34 -1
  219. package/node/lib/fbs/transport/produce-response.js +34 -1
  220. package/node/lib/fbs/transport/recv-rtp-header-extensions.js +34 -1
  221. package/node/lib/fbs/transport/restart-ice-response.js +34 -1
  222. package/node/lib/fbs/transport/rtp-listener.js +34 -1
  223. package/node/lib/fbs/transport/sctp-listener.js +34 -1
  224. package/node/lib/fbs/transport/sctp-negotiated-capabilities-notification.d.ts +22 -0
  225. package/node/lib/fbs/transport/sctp-negotiated-capabilities-notification.d.ts.map +1 -0
  226. package/node/lib/fbs/transport/sctp-negotiated-capabilities-notification.js +93 -0
  227. package/node/lib/fbs/transport/sctp-state-change-notification.js +34 -1
  228. package/node/lib/fbs/transport/send-rtcp-notification.js +34 -1
  229. package/node/lib/fbs/transport/set-max-incoming-bitrate-request.js +34 -1
  230. package/node/lib/fbs/transport/set-max-outgoing-bitrate-request.js +34 -1
  231. package/node/lib/fbs/transport/set-min-outgoing-bitrate-request.js +34 -1
  232. package/node/lib/fbs/transport/socket-flags.js +34 -1
  233. package/node/lib/fbs/transport/stats.js +34 -1
  234. package/node/lib/fbs/transport/trace-notification.js +34 -1
  235. package/node/lib/fbs/transport/tuple.js +34 -1
  236. package/node/lib/fbs/transport.d.ts +1 -0
  237. package/node/lib/fbs/transport.d.ts.map +1 -1
  238. package/node/lib/fbs/transport.js +5 -2
  239. package/node/lib/fbs/web-rtc-server/dump-response.js +34 -1
  240. package/node/lib/fbs/web-rtc-server/ice-user-name-fragment.js +34 -1
  241. package/node/lib/fbs/web-rtc-server/ip-port.js +34 -1
  242. package/node/lib/fbs/web-rtc-server/tuple-hash.js +34 -1
  243. package/node/lib/fbs/web-rtc-transport/connect-request.js +34 -1
  244. package/node/lib/fbs/web-rtc-transport/connect-response.js +34 -1
  245. package/node/lib/fbs/web-rtc-transport/dtls-parameters.js +34 -1
  246. package/node/lib/fbs/web-rtc-transport/dtls-state-change-notification.js +34 -1
  247. package/node/lib/fbs/web-rtc-transport/dump-response.js +34 -1
  248. package/node/lib/fbs/web-rtc-transport/fingerprint.js +34 -1
  249. package/node/lib/fbs/web-rtc-transport/get-stats-response.js +34 -1
  250. package/node/lib/fbs/web-rtc-transport/ice-candidate.js +34 -1
  251. package/node/lib/fbs/web-rtc-transport/ice-parameters.js +34 -1
  252. package/node/lib/fbs/web-rtc-transport/ice-selected-tuple-change-notification.js +34 -1
  253. package/node/lib/fbs/web-rtc-transport/ice-state-change-notification.js +34 -1
  254. package/node/lib/fbs/web-rtc-transport/listen-individual.js +34 -1
  255. package/node/lib/fbs/web-rtc-transport/listen-server.js +34 -1
  256. package/node/lib/fbs/web-rtc-transport/web-rtc-transport-options.js +34 -1
  257. package/node/lib/fbs/worker/channel-message-handlers.js +34 -1
  258. package/node/lib/fbs/worker/close-router-request.js +34 -1
  259. package/node/lib/fbs/worker/close-web-rtc-server-request.js +34 -1
  260. package/node/lib/fbs/worker/create-router-request.js +34 -1
  261. package/node/lib/fbs/worker/create-web-rtc-server-request.js +34 -1
  262. package/node/lib/fbs/worker/dump-response.js +34 -1
  263. package/node/lib/fbs/worker/resource-usage-response.js +34 -1
  264. package/node/lib/fbs/worker/update-settings-request.js +34 -1
  265. package/node/lib/index.d.ts +1 -1
  266. package/node/lib/index.d.ts.map +1 -1
  267. package/node/lib/index.js +37 -5
  268. package/node/lib/ortc.js +36 -3
  269. package/node/lib/rtpParametersFbsUtils.js +34 -1
  270. package/node/lib/rtpStreamStatsFbsUtils.js +35 -2
  271. package/node/lib/sctpParametersFbsUtils.d.ts +2 -2
  272. package/node/lib/sctpParametersFbsUtils.d.ts.map +1 -1
  273. package/node/lib/sctpParametersFbsUtils.js +44 -7
  274. package/node/lib/sctpParametersTypes.d.ts +10 -46
  275. package/node/lib/sctpParametersTypes.d.ts.map +1 -1
  276. package/node/lib/srtpParametersFbsUtils.js +34 -1
  277. package/node/lib/test/test-ActiveSpeakerObserver.js +35 -2
  278. package/node/lib/test/test-AudioLevelObserver.js +35 -2
  279. package/node/lib/test/test-Consumer.js +37 -4
  280. package/node/lib/test/test-DataConsumer.js +35 -2
  281. package/node/lib/test/test-DataProducer.js +35 -2
  282. package/node/lib/test/test-DirectTransport.js +36 -8
  283. package/node/lib/test/test-PipeTransport.js +35 -2
  284. package/node/lib/test/test-PlainTransport.js +45 -12
  285. package/node/lib/test/test-Producer.js +37 -4
  286. package/node/lib/test/test-Router.js +35 -2
  287. package/node/lib/test/test-WebRtcServer.js +34 -1
  288. package/node/lib/test/test-WebRtcTransport.js +51 -22
  289. package/node/lib/test/test-Worker.js +37 -4
  290. package/node/lib/test/test-mediasoup.js +36 -3
  291. package/node/lib/test/test-multiopus.js +35 -2
  292. package/node/lib/test/test-ortc.js +34 -1
  293. package/node/lib/test/test-werift-sctp.js +39 -5
  294. package/npm-scripts.mjs +2 -2
  295. package/package.json +13 -11
  296. package/worker/deps/libwebrtc/LICENSE +5 -0
  297. package/worker/deps/libwebrtc/README.md +3 -3
  298. package/worker/deps/libwebrtc/libwebrtc/mediasoup_helpers.h +13 -10
  299. package/worker/fbs/dataConsumer.fbs +7 -2
  300. package/worker/fbs/dataProducer.fbs +1 -0
  301. package/worker/fbs/notification.fbs +2 -0
  302. package/worker/fbs/sctpAssociation.fbs +4 -0
  303. package/worker/fbs/sctpParameters.fbs +5 -12
  304. package/worker/fbs/transport.fbs +12 -8
  305. package/worker/fuzzer/src/RTC/FuzzerDtlsTransport.cpp +13 -3
  306. package/worker/fuzzer/src/RTC/FuzzerRateCalculator.cpp +2 -2
  307. package/worker/fuzzer/src/RTC/FuzzerSeqManager.cpp +1 -1
  308. package/worker/fuzzer/src/RTC/FuzzerTrendCalculator.cpp +5 -5
  309. package/worker/fuzzer/src/RTC/ICE/FuzzerStunPacket.cpp +9 -6
  310. package/worker/fuzzer/src/RTC/RTP/FuzzerRetransmissionBuffer.cpp +1 -1
  311. package/worker/fuzzer/src/RTC/RTP/FuzzerRtpStreamSend.cpp +14 -2
  312. package/worker/fuzzer/src/RTC/SCTP/association/FuzzerStateCookie.cpp +1 -1
  313. package/worker/fuzzer/src/RTC/SCTP/packet/FuzzerPacket.cpp +5 -2
  314. package/worker/fuzzer/src/fuzzer.cpp +3 -10
  315. package/worker/include/Channel/ChannelMessageRegistrator.hpp +39 -0
  316. package/worker/include/Channel/ChannelMessageRegistratorInterface.hpp +32 -0
  317. package/worker/include/Channel/ChannelRequest.hpp +1 -1
  318. package/worker/include/Channel/ChannelSocket.hpp +1 -1
  319. package/worker/include/DepLibUV.hpp +1 -1
  320. package/worker/include/DepLibUring.hpp +3 -3
  321. package/worker/include/Logger.hpp +4 -4
  322. package/worker/include/MediaSoupErrors.hpp +1 -1
  323. package/worker/include/RTC/ActiveSpeakerObserver.hpp +11 -9
  324. package/worker/include/RTC/AudioLevelObserver.hpp +7 -7
  325. package/worker/include/RTC/Consumer.hpp +3 -3
  326. package/worker/include/RTC/DataConsumer.hpp +13 -17
  327. package/worker/include/RTC/DataProducer.hpp +6 -9
  328. package/worker/include/RTC/DirectTransport.hpp +4 -6
  329. package/worker/include/RTC/DtlsTransport.hpp +13 -11
  330. package/worker/include/RTC/ICE/IceServer.hpp +8 -5
  331. package/worker/include/RTC/ICE/StunPacket.hpp +1 -1
  332. package/worker/include/RTC/KeyFrameRequestManager.hpp +15 -12
  333. package/worker/include/RTC/NackGenerator.hpp +8 -6
  334. package/worker/include/RTC/PipeConsumer.hpp +1 -2
  335. package/worker/include/RTC/PipeTransport.hpp +4 -6
  336. package/worker/include/RTC/PlainTransport.hpp +4 -6
  337. package/worker/include/RTC/PortManager.hpp +1 -1
  338. package/worker/include/RTC/Producer.hpp +3 -3
  339. package/worker/include/RTC/RTCP/FeedbackPs.hpp +1 -1
  340. package/worker/include/RTC/RTCP/FeedbackRtp.hpp +1 -1
  341. package/worker/include/RTC/RTCP/FeedbackRtpNack.hpp +1 -1
  342. package/worker/include/RTC/RTCP/ReceiverReport.hpp +1 -1
  343. package/worker/include/RTC/RTP/Packet.hpp +2 -2
  344. package/worker/include/RTC/RTP/RtpStream.hpp +17 -12
  345. package/worker/include/RTC/RTP/RtpStreamRecv.hpp +8 -6
  346. package/worker/include/RTC/RTP/RtpStreamSend.hpp +4 -1
  347. package/worker/include/RTC/RTP/RtxStream.hpp +3 -1
  348. package/worker/include/RTC/RTP/SharedPacket.hpp +1 -1
  349. package/worker/include/RTC/RateCalculator.hpp +5 -2
  350. package/worker/include/RTC/Router.hpp +7 -8
  351. package/worker/include/RTC/RtpObserver.hpp +3 -3
  352. package/worker/include/RTC/SCTP/association/Association.hpp +53 -19
  353. package/worker/include/RTC/SCTP/association/AssociationListenerDeferrer.hpp +14 -6
  354. package/worker/include/RTC/SCTP/association/HeartbeatHandler.hpp +18 -14
  355. package/worker/include/RTC/SCTP/association/PacketSender.hpp +3 -3
  356. package/worker/include/RTC/SCTP/association/StateCookie.hpp +1 -1
  357. package/worker/include/RTC/SCTP/association/StreamResetHandler.hpp +49 -35
  358. package/worker/include/RTC/SCTP/association/TransmissionControlBlock.hpp +114 -31
  359. package/worker/include/RTC/SCTP/association/{TCBContext.hpp → TransmissionControlBlockContextInterface.hpp} +14 -8
  360. package/worker/include/RTC/SCTP/packet/Chunk.hpp +3 -3
  361. package/worker/include/RTC/SCTP/packet/TLV.hpp +1 -1
  362. package/worker/include/RTC/SCTP/packet/UserData.hpp +61 -17
  363. package/worker/include/RTC/SCTP/packet/chunks/AnyDataChunk.hpp +1 -1
  364. package/worker/include/RTC/SCTP/packet/chunks/AnyForwardTsnChunk.hpp +9 -9
  365. package/worker/include/RTC/SCTP/packet/chunks/AnyInitChunk.hpp +1 -1
  366. package/worker/include/RTC/SCTP/packet/chunks/DataChunk.hpp +4 -2
  367. package/worker/include/RTC/SCTP/packet/chunks/ForwardTsnChunk.hpp +3 -3
  368. package/worker/include/RTC/SCTP/packet/chunks/IDataChunk.hpp +4 -2
  369. package/worker/include/RTC/SCTP/packet/chunks/IForwardTsnChunk.hpp +3 -3
  370. package/worker/include/RTC/SCTP/packet/chunks/InitAckChunk.hpp +1 -1
  371. package/worker/include/RTC/SCTP/packet/chunks/InitChunk.hpp +1 -1
  372. package/worker/include/RTC/SCTP/packet/chunks/SackChunk.hpp +10 -3
  373. package/worker/include/RTC/SCTP/packet/chunks/ShutdownChunk.hpp +1 -1
  374. package/worker/include/RTC/SCTP/packet/errorCauses/InvalidStreamIdentifierErrorCause.hpp +1 -1
  375. package/worker/include/RTC/SCTP/packet/errorCauses/MissingMandatoryParameterErrorCause.hpp +1 -1
  376. package/worker/include/RTC/SCTP/packet/errorCauses/NoUserDataErrorCause.hpp +1 -1
  377. package/worker/include/RTC/SCTP/packet/errorCauses/StaleCookieErrorCause.hpp +1 -1
  378. package/worker/include/RTC/SCTP/packet/parameters/AddIncomingStreamsRequestParameter.hpp +1 -1
  379. package/worker/include/RTC/SCTP/packet/parameters/AddOutgoingStreamsRequestParameter.hpp +1 -1
  380. package/worker/include/RTC/SCTP/packet/parameters/CookiePreservativeParameter.hpp +1 -1
  381. package/worker/include/RTC/SCTP/packet/parameters/IncomingSsnResetRequestParameter.hpp +1 -1
  382. package/worker/include/RTC/SCTP/packet/parameters/OutgoingSsnResetRequestParameter.hpp +1 -1
  383. package/worker/include/RTC/SCTP/packet/parameters/ReconfigurationResponseParameter.hpp +1 -1
  384. package/worker/include/RTC/SCTP/packet/parameters/SsnTsnResetRequestParameter.hpp +1 -1
  385. package/worker/include/RTC/SCTP/packet/parameters/SupportedAddressTypesParameter.hpp +1 -1
  386. package/worker/include/RTC/SCTP/packet/parameters/SupportedExtensionsParameter.hpp +1 -1
  387. package/worker/include/RTC/SCTP/packet/parameters/ZeroChecksumAcceptableParameter.hpp +1 -1
  388. package/worker/include/RTC/SCTP/public/AssociationInterface.hpp +22 -2
  389. package/worker/include/RTC/SCTP/public/{AssociationListener.hpp → AssociationListenerInterface.hpp} +5 -5
  390. package/worker/include/RTC/SCTP/public/Message.hpp +26 -10
  391. package/worker/include/RTC/SCTP/public/SctpOptions.hpp +28 -19
  392. package/worker/include/RTC/SCTP/public/SctpTypes.hpp +21 -0
  393. package/worker/include/RTC/SCTP/rx/DataTracker.hpp +277 -0
  394. package/worker/include/RTC/SCTP/rx/InterleavedReassemblyStreams.hpp +116 -0
  395. package/worker/include/RTC/SCTP/rx/ReassemblyQueue.hpp +202 -0
  396. package/worker/include/RTC/SCTP/rx/ReassemblyStreamsInterface.hpp +83 -0
  397. package/worker/include/RTC/SCTP/rx/TraditionalReassemblyStreams.hpp +183 -0
  398. package/worker/include/RTC/SCTP/tx/OutstandingData.hpp +595 -0
  399. package/worker/include/RTC/SCTP/tx/RetransmissionErrorCounter.hpp +3 -3
  400. package/worker/include/RTC/SCTP/tx/RetransmissionQueue.hpp +329 -0
  401. package/worker/include/RTC/SCTP/tx/RetransmissionTimeout.hpp +11 -10
  402. package/worker/include/RTC/SCTP/tx/RoundRobinSendQueue.hpp +356 -0
  403. package/worker/include/RTC/SCTP/tx/SendQueueInterface.hpp +180 -0
  404. package/worker/include/RTC/SCTP/tx/StreamScheduler.hpp +235 -0
  405. package/worker/include/RTC/SenderBandwidthEstimator.hpp +5 -1
  406. package/worker/include/RTC/Serializable.hpp +11 -3
  407. package/worker/include/RTC/SimpleConsumer.hpp +1 -2
  408. package/worker/include/RTC/SimulcastConsumer.hpp +1 -2
  409. package/worker/include/RTC/SvcConsumer.hpp +1 -2
  410. package/worker/include/RTC/TcpServer.hpp +2 -2
  411. package/worker/include/RTC/Transport.hpp +65 -86
  412. package/worker/include/RTC/TransportCongestionControlClient.hpp +8 -5
  413. package/worker/include/RTC/TransportCongestionControlServer.hpp +8 -5
  414. package/worker/include/RTC/TransportTuple.hpp +1 -1
  415. package/worker/include/RTC/UdpSocket.hpp +1 -1
  416. package/worker/include/RTC/WebRtcServer.hpp +3 -3
  417. package/worker/include/RTC/WebRtcTransport.hpp +5 -7
  418. package/worker/include/Settings.hpp +2 -3
  419. package/worker/include/Shared.hpp +64 -0
  420. package/worker/include/SharedInterface.hpp +77 -0
  421. package/worker/include/Utils/UnwrappedSequenceNumber.hpp +270 -0
  422. package/worker/include/Utils.hpp +10 -4
  423. package/worker/include/Worker.hpp +6 -6
  424. package/worker/include/common.hpp +12 -12
  425. package/worker/include/handles/BackoffTimerHandle.hpp +28 -67
  426. package/worker/include/handles/BackoffTimerHandleInterface.hpp +123 -0
  427. package/worker/include/handles/TimerHandle.hpp +29 -20
  428. package/worker/include/handles/TimerHandleInterface.hpp +43 -0
  429. package/worker/meson.build +45 -29
  430. package/worker/meson_options.txt +2 -1
  431. package/worker/mocks/include/Channel/MockChannelMessageRegistrator.hpp +45 -0
  432. package/worker/mocks/include/MockShared.hpp +90 -0
  433. package/worker/mocks/include/RTC/SCTP/association/MockAssociationListener.hpp +308 -0
  434. package/worker/mocks/include/RTC/SCTP/association/MockTransmissionControlBlockContext.hpp +183 -0
  435. package/worker/mocks/include/RTC/SCTP/tx/MockSendQueue.hpp +262 -0
  436. package/worker/mocks/include/handles/MockBackoffTimerHandle.hpp +153 -0
  437. package/worker/mocks/include/handles/MockTimerHandle.hpp +74 -0
  438. package/worker/mocks/include/mockTypes.hpp +15 -0
  439. package/worker/mocks/src/Channel/MockChannelMessageRegistrator.cpp +128 -0
  440. package/worker/mocks/src/MockShared.cpp +46 -0
  441. package/worker/mocks/src/RTC/SCTP/association/MockTransmissionControlBlockContext.cpp +39 -0
  442. package/worker/mocks/src/handles/MockBackoffTimerHandle.cpp +127 -0
  443. package/worker/scripts/clang-scripts.mjs +5 -1
  444. package/worker/scripts/package-lock.json +6 -7
  445. package/worker/src/Channel/ChannelMessageRegistrator.cpp +125 -0
  446. package/worker/src/Channel/ChannelSocket.cpp +3 -4
  447. package/worker/src/DepLibUV.cpp +1 -1
  448. package/worker/src/DepLibUring.cpp +3 -1
  449. package/worker/src/Logger.cpp +1 -1
  450. package/worker/src/MediaSoupErrors.cpp +2 -0
  451. package/worker/src/RTC/ActiveSpeakerObserver.cpp +14 -14
  452. package/worker/src/RTC/AudioLevelObserver.cpp +12 -10
  453. package/worker/src/RTC/Consumer.cpp +28 -26
  454. package/worker/src/RTC/DataConsumer.cpp +61 -71
  455. package/worker/src/RTC/DataProducer.cpp +16 -11
  456. package/worker/src/RTC/DirectTransport.cpp +21 -20
  457. package/worker/src/RTC/DtlsTransport.cpp +4 -4
  458. package/worker/src/RTC/ICE/IceServer.cpp +6 -5
  459. package/worker/src/RTC/ICE/StunPacket.cpp +1 -1
  460. package/worker/src/RTC/KeyFrameRequestManager.cpp +15 -15
  461. package/worker/src/RTC/NackGenerator.cpp +6 -6
  462. package/worker/src/RTC/PipeConsumer.cpp +6 -5
  463. package/worker/src/RTC/PipeTransport.cpp +9 -22
  464. package/worker/src/RTC/PlainTransport.cpp +16 -28
  465. package/worker/src/RTC/Producer.cpp +40 -39
  466. package/worker/src/RTC/RTCP/FeedbackPsAfb.cpp +1 -1
  467. package/worker/src/RTC/RTCP/FeedbackPsRpsi.cpp +1 -2
  468. package/worker/src/RTC/RTCP/FeedbackRtpTransport.cpp +1 -1
  469. package/worker/src/RTC/RTCP/XR.cpp +1 -1
  470. package/worker/src/RTC/RTP/Packet.cpp +3 -1
  471. package/worker/src/RTC/RTP/ProbationGenerator.cpp +4 -4
  472. package/worker/src/RTC/RTP/RetransmissionBuffer.cpp +1 -1
  473. package/worker/src/RTC/RTP/RtpStream.cpp +17 -10
  474. package/worker/src/RTC/RTP/RtpStreamRecv.cpp +16 -14
  475. package/worker/src/RTC/RTP/RtpStreamSend.cpp +12 -9
  476. package/worker/src/RTC/RTP/RtxStream.cpp +7 -7
  477. package/worker/src/RTC/RTP/SharedPacket.cpp +3 -3
  478. package/worker/src/RTC/RateCalculator.cpp +1 -2
  479. package/worker/src/RTC/Router.cpp +61 -38
  480. package/worker/src/RTC/RtpDictionaries/RtpCodecMimeType.cpp +1 -1
  481. package/worker/src/RTC/RtpObserver.cpp +2 -1
  482. package/worker/src/RTC/SCTP/LICENSE +44 -0
  483. package/worker/src/RTC/SCTP/association/Association.cpp +417 -411
  484. package/worker/src/RTC/SCTP/association/AssociationListenerDeferrer.cpp +46 -13
  485. package/worker/src/RTC/SCTP/association/HeartbeatHandler.cpp +47 -43
  486. package/worker/src/RTC/SCTP/association/PacketSender.cpp +8 -8
  487. package/worker/src/RTC/SCTP/association/StreamResetHandler.cpp +113 -101
  488. package/worker/src/RTC/SCTP/association/TransmissionControlBlock.cpp +291 -62
  489. package/worker/src/RTC/SCTP/packet/Chunk.cpp +5 -1
  490. package/worker/src/RTC/SCTP/packet/Packet.cpp +8 -1
  491. package/worker/src/RTC/SCTP/packet/chunks/DataChunk.cpp +17 -0
  492. package/worker/src/RTC/SCTP/packet/chunks/ForwardTsnChunk.cpp +4 -4
  493. package/worker/src/RTC/SCTP/packet/chunks/IDataChunk.cpp +25 -0
  494. package/worker/src/RTC/SCTP/packet/chunks/IForwardTsnChunk.cpp +10 -7
  495. package/worker/src/RTC/SCTP/packet/chunks/SackChunk.cpp +21 -4
  496. package/worker/src/RTC/SCTP/packet/chunks/ShutdownCompleteChunk.cpp +1 -1
  497. package/worker/src/RTC/SCTP/packet/errorCauses/NoUserDataErrorCause.cpp +1 -1
  498. package/worker/src/RTC/SCTP/packet/errorCauses/ProtocolViolationErrorCause.cpp +2 -2
  499. package/worker/src/RTC/SCTP/packet/errorCauses/UserInitiatedAbortErrorCause.cpp +1 -1
  500. package/worker/src/RTC/SCTP/public/Message.cpp +8 -0
  501. package/worker/src/RTC/SCTP/public/SctpOptions.cpp +90 -0
  502. package/worker/src/RTC/SCTP/rx/DataTracker.cpp +471 -0
  503. package/worker/src/RTC/SCTP/rx/InterleavedReassemblyStreams.cpp +327 -0
  504. package/worker/src/RTC/SCTP/rx/ReassemblyQueue.cpp +288 -0
  505. package/worker/src/RTC/SCTP/rx/TraditionalReassemblyStreams.cpp +453 -0
  506. package/worker/src/RTC/SCTP/tx/OutstandingData.cpp +912 -0
  507. package/worker/src/RTC/SCTP/tx/RetransmissionQueue.cpp +786 -0
  508. package/worker/src/RTC/SCTP/tx/RetransmissionTimeout.cpp +2 -2
  509. package/worker/src/RTC/SCTP/tx/RoundRobinSendQueue.cpp +752 -0
  510. package/worker/src/RTC/SCTP/tx/StreamScheduler.cpp +257 -0
  511. package/worker/src/RTC/SenderBandwidthEstimator.cpp +7 -5
  512. package/worker/src/RTC/SimpleConsumer.cpp +11 -11
  513. package/worker/src/RTC/SimulcastConsumer.cpp +16 -16
  514. package/worker/src/RTC/SrtpSession.cpp +1 -1
  515. package/worker/src/RTC/SvcConsumer.cpp +16 -16
  516. package/worker/src/RTC/TcpConnection.cpp +1 -1
  517. package/worker/src/RTC/Transport.cpp +497 -563
  518. package/worker/src/RTC/TransportCongestionControlClient.cpp +9 -8
  519. package/worker/src/RTC/TransportCongestionControlServer.cpp +5 -5
  520. package/worker/src/RTC/WebRtcServer.cpp +5 -4
  521. package/worker/src/RTC/WebRtcTransport.cpp +44 -39
  522. package/worker/src/Settings.cpp +9 -28
  523. package/worker/src/Shared.cpp +35 -0
  524. package/worker/src/Utils/Crypto.cpp +1 -1
  525. package/worker/src/Utils/String.cpp +1 -1
  526. package/worker/src/Worker.cpp +19 -48
  527. package/worker/src/handles/BackoffTimerHandle.cpp +34 -21
  528. package/worker/src/handles/TimerHandle.cpp +5 -4
  529. package/worker/src/handles/UdpSocketHandle.cpp +1 -1
  530. package/worker/src/lib.cpp +17 -16
  531. package/worker/subprojects/catch2.wrap +6 -6
  532. package/worker/tasks.py +1 -1
  533. package/worker/test/include/RTC/ICE/iceCommon.hpp +8 -7
  534. package/worker/test/include/RTC/RTP/rtpCommon.hpp +7 -6
  535. package/worker/test/include/RTC/SCTP/sctpCommon.hpp +16 -10
  536. package/worker/test/include/catch2Macros.hpp +31 -0
  537. package/worker/test/src/RTC/ICE/TestStunPacket.cpp +3 -3
  538. package/worker/test/src/RTC/ICE/iceCommon.cpp +2 -2
  539. package/worker/test/src/RTC/RTP/Codecs/TestVP8.cpp +1 -1
  540. package/worker/test/src/RTC/RTP/Codecs/TestVP9.cpp +1 -1
  541. package/worker/test/src/RTC/RTP/TestPacket.cpp +3 -3
  542. package/worker/test/src/RTC/RTP/TestRtpStreamRecv.cpp +16 -9
  543. package/worker/test/src/RTC/RTP/TestRtpStreamSend.cpp +38 -23
  544. package/worker/test/src/RTC/RTP/TestSharedPacket.cpp +1 -1
  545. package/worker/test/src/RTC/RTP/rtpCommon.cpp +2 -2
  546. package/worker/test/src/RTC/SCTP/association/TestHeartbeatHandler.cpp +292 -0
  547. package/worker/test/src/RTC/SCTP/association/TestNegotiatedCapabilities.cpp +1 -1
  548. package/worker/test/src/RTC/SCTP/association/TestStateCookie.cpp +1 -1
  549. package/worker/test/src/RTC/SCTP/association/TestTransmissionControlBlock.cpp +99 -0
  550. package/worker/test/src/RTC/SCTP/packet/TestChunk.cpp +1 -1
  551. package/worker/test/src/RTC/SCTP/packet/TestPacket.cpp +1 -1
  552. package/worker/test/src/RTC/SCTP/packet/chunks/TestAbortAssociationChunk.cpp +1 -1
  553. package/worker/test/src/RTC/SCTP/packet/chunks/TestCookieAckChunk.cpp +1 -1
  554. package/worker/test/src/RTC/SCTP/packet/chunks/TestCookieEchoChunk.cpp +1 -1
  555. package/worker/test/src/RTC/SCTP/packet/chunks/TestDataChunk.cpp +77 -7
  556. package/worker/test/src/RTC/SCTP/packet/chunks/TestForwardTsnChunk.cpp +35 -26
  557. package/worker/test/src/RTC/SCTP/packet/chunks/TestHeartbeatAckChunk.cpp +1 -1
  558. package/worker/test/src/RTC/SCTP/packet/chunks/TestHeartbeatRequestChunk.cpp +1 -1
  559. package/worker/test/src/RTC/SCTP/packet/chunks/TestIDataChunk.cpp +77 -7
  560. package/worker/test/src/RTC/SCTP/packet/chunks/TestIForwardTsnChunk.cpp +59 -27
  561. package/worker/test/src/RTC/SCTP/packet/chunks/TestInitAckChunk.cpp +1 -1
  562. package/worker/test/src/RTC/SCTP/packet/chunks/TestInitChunk.cpp +1 -1
  563. package/worker/test/src/RTC/SCTP/packet/chunks/TestOperationErrorChunk.cpp +1 -1
  564. package/worker/test/src/RTC/SCTP/packet/chunks/TestReConfigChunk.cpp +1 -1
  565. package/worker/test/src/RTC/SCTP/packet/chunks/TestSackChunk.cpp +73 -35
  566. package/worker/test/src/RTC/SCTP/packet/chunks/TestShutdownAckChunk.cpp +1 -1
  567. package/worker/test/src/RTC/SCTP/packet/chunks/TestShutdownChunk.cpp +1 -1
  568. package/worker/test/src/RTC/SCTP/packet/chunks/TestShutdownCompleteChunk.cpp +1 -1
  569. package/worker/test/src/RTC/SCTP/packet/chunks/TestUnknownChunk.cpp +1 -1
  570. package/worker/test/src/RTC/SCTP/packet/errorCauses/TestCookieReceivedWhileShuttingDownErrorCause.cpp +1 -1
  571. package/worker/test/src/RTC/SCTP/packet/errorCauses/TestInvalidMandatoryParameterErrorCause.cpp +1 -1
  572. package/worker/test/src/RTC/SCTP/packet/errorCauses/TestInvalidStreamIdentifierErrorCause.cpp +1 -1
  573. package/worker/test/src/RTC/SCTP/packet/errorCauses/TestMissingMandatoryParameterErrorCause.cpp +1 -1
  574. package/worker/test/src/RTC/SCTP/packet/errorCauses/TestNoUserDataErrorCause.cpp +1 -1
  575. package/worker/test/src/RTC/SCTP/packet/errorCauses/TestOutOfResourceErrorCause.cpp +1 -1
  576. package/worker/test/src/RTC/SCTP/packet/errorCauses/TestProtocolViolationErrorCause.cpp +1 -1
  577. package/worker/test/src/RTC/SCTP/packet/errorCauses/TestRestartOfAnAssociationWithNewAddressesErrorCause.cpp +1 -1
  578. package/worker/test/src/RTC/SCTP/packet/errorCauses/TestStaleCookieErrorCause.cpp +1 -1
  579. package/worker/test/src/RTC/SCTP/packet/errorCauses/TestUnknownErrorCause.cpp +1 -1
  580. package/worker/test/src/RTC/SCTP/packet/errorCauses/TestUnrecognizedChunkTypeErrorCause.cpp +1 -1
  581. package/worker/test/src/RTC/SCTP/packet/errorCauses/TestUnrecognizedParametersErrorCause.cpp +1 -1
  582. package/worker/test/src/RTC/SCTP/packet/errorCauses/TestUnresolvableAddressErrorCause.cpp +1 -1
  583. package/worker/test/src/RTC/SCTP/packet/errorCauses/TestUserInitiatedAbortErrorCause.cpp +1 -1
  584. package/worker/test/src/RTC/SCTP/packet/parameters/TestAddIncomingStreamsRequestParameter.cpp +1 -1
  585. package/worker/test/src/RTC/SCTP/packet/parameters/TestAddOutgoingStreamsRequestParameter.cpp +1 -1
  586. package/worker/test/src/RTC/SCTP/packet/parameters/TestCookiePreservativeParameter.cpp +1 -1
  587. package/worker/test/src/RTC/SCTP/packet/parameters/TestForwardTsnSupportedParameter.cpp +1 -1
  588. package/worker/test/src/RTC/SCTP/packet/parameters/TestHeartbeatInfoParameter.cpp +1 -1
  589. package/worker/test/src/RTC/SCTP/packet/parameters/TestIPv4AddressParameter.cpp +1 -1
  590. package/worker/test/src/RTC/SCTP/packet/parameters/TestIPv6AddressParameter.cpp +1 -1
  591. package/worker/test/src/RTC/SCTP/packet/parameters/TestIncomingSsnResetRequestParameter.cpp +1 -1
  592. package/worker/test/src/RTC/SCTP/packet/parameters/TestOutgoingSsnResetRequestParameter.cpp +1 -1
  593. package/worker/test/src/RTC/SCTP/packet/parameters/TestReconfigurationResponseParameter.cpp +1 -1
  594. package/worker/test/src/RTC/SCTP/packet/parameters/TestSsnTsnResetRequestParameter.cpp +1 -1
  595. package/worker/test/src/RTC/SCTP/packet/parameters/TestStateCookieParameter.cpp +1 -1
  596. package/worker/test/src/RTC/SCTP/packet/parameters/TestSupportedAddressTypesParameter.cpp +1 -1
  597. package/worker/test/src/RTC/SCTP/packet/parameters/TestSupportedExtensionsParameter.cpp +1 -1
  598. package/worker/test/src/RTC/SCTP/packet/parameters/TestUnknownParameter.cpp +1 -1
  599. package/worker/test/src/RTC/SCTP/packet/parameters/TestUnrecognizedParameterParameter.cpp +1 -1
  600. package/worker/test/src/RTC/SCTP/packet/parameters/TestZeroChecksumAcceptableParameter.cpp +1 -1
  601. package/worker/test/src/RTC/SCTP/rx/TestDataTracker.cpp +1117 -0
  602. package/worker/test/src/RTC/SCTP/rx/TestInterleavedReassemblyStreams.cpp +565 -0
  603. package/worker/test/src/RTC/SCTP/rx/TestReassemblyQueue.cpp +557 -0
  604. package/worker/test/src/RTC/SCTP/rx/TestTraditionalReassemblyStreams.cpp +555 -0
  605. package/worker/test/src/RTC/SCTP/sctpCommon.cpp +2 -2
  606. package/worker/test/src/RTC/SCTP/tx/TestOutstandingData.cpp +1248 -0
  607. package/worker/test/src/RTC/SCTP/tx/TestRetransmissionErrorCounter.cpp +4 -0
  608. package/worker/test/src/RTC/SCTP/tx/TestRetransmissionQueue.cpp +2218 -0
  609. package/worker/test/src/RTC/SCTP/tx/TestRetransmissionTimeout.cpp +33 -33
  610. package/worker/test/src/RTC/SCTP/tx/TestRoundRobinSendQueue.cpp +1130 -0
  611. package/worker/test/src/RTC/SCTP/tx/TestStreamScheduler.cpp +721 -0
  612. package/worker/test/src/RTC/TestKeyFrameRequestManager.cpp +20 -30
  613. package/worker/test/src/RTC/TestNackGenerator.cpp +11 -8
  614. package/worker/test/src/RTC/TestRateCalculator.cpp +6 -7
  615. package/worker/test/src/RTC/TestSimpleConsumer.cpp +11 -11
  616. package/worker/test/src/RTC/TestTransportCongestionControlServer.cpp +15 -3
  617. package/worker/test/src/Utils/TestByte.cpp +98 -0
  618. package/worker/test/src/{RTC/SCTP/common → Utils}/TestUnwrappedSequenceNumber.cpp +2 -2
  619. package/worker/test/src/testHelpers.cpp +1 -1
  620. package/worker/test/src/tests.cpp +0 -12
  621. package/node/lib/fbs/consumer/degrade-request.d.ts +0 -30
  622. package/node/lib/fbs/consumer/degrade-request.d.ts.map +0 -1
  623. package/node/lib/fbs/consumer/degrade-request.js +0 -91
  624. package/node/lib/fbs/consumer/enable-delay-and-loss-request.d.ts +0 -24
  625. package/node/lib/fbs/consumer/enable-delay-and-loss-request.d.ts.map +0 -1
  626. package/node/lib/fbs/consumer/enable-delay-and-loss-request.js +0 -69
  627. package/node/lib/fbs/producer/degrade-request.d.ts +0 -30
  628. package/node/lib/fbs/producer/degrade-request.d.ts.map +0 -1
  629. package/node/lib/fbs/producer/degrade-request.js +0 -91
  630. package/node/lib/fbs/worker/close-notification.d.ts +0 -18
  631. package/node/lib/fbs/worker/close-notification.d.ts.map +0 -1
  632. package/node/lib/fbs/worker/close-notification.js +0 -45
  633. package/node/lib/fbs/worker/close-request.d.ts +0 -18
  634. package/node/lib/fbs/worker/close-request.d.ts.map +0 -1
  635. package/node/lib/fbs/worker/close-request.js +0 -45
  636. package/node/lib/fbs/worker/close-worker-notification.d.ts +0 -18
  637. package/node/lib/fbs/worker/close-worker-notification.d.ts.map +0 -1
  638. package/node/lib/fbs/worker/close-worker-notification.js +0 -45
  639. package/worker/include/ChannelMessageRegistrator.hpp +0 -30
  640. package/worker/include/DepUsrSCTP.hpp +0 -48
  641. package/worker/include/RTC/SCTP/TODO_SCTP.md +0 -43
  642. package/worker/include/RTC/SCTP/common/UnwrappedSequenceNumber.hpp +0 -274
  643. package/worker/include/RTC/SctpAssociation.hpp +0 -147
  644. package/worker/include/RTC/Shared.hpp +0 -23
  645. package/worker/src/ChannelMessageRegistrator.cpp +0 -119
  646. package/worker/src/DepUsrSCTP.cpp +0 -277
  647. package/worker/src/RTC/SctpAssociation.cpp +0 -1175
  648. package/worker/src/RTC/Shared.cpp +0 -23
  649. package/worker/subprojects/usrsctp.wrap +0 -8
@@ -0,0 +1,2218 @@
1
+ #include "common.hpp"
2
+ #include "handles/BackoffTimerHandleInterface.hpp"
3
+ #include "RTC/SCTP/packet/Packet.hpp"
4
+ #include "RTC/SCTP/packet/UserData.hpp"
5
+ #include "RTC/SCTP/packet/chunks/AnyForwardTsnChunk.hpp"
6
+ #include "RTC/SCTP/packet/chunks/DataChunk.hpp"
7
+ #include "RTC/SCTP/packet/chunks/SackChunk.hpp"
8
+ #include "RTC/SCTP/public/SctpOptions.hpp"
9
+ #include "RTC/SCTP/tx/RetransmissionQueue.hpp"
10
+ #include "RTC/SCTP/tx/SendQueueInterface.hpp"
11
+ #include "Utils.hpp"
12
+ #include "test/include/RTC/SCTP/sctpCommon.hpp"
13
+ #include "test/include/catch2Macros.hpp"
14
+ #include "mocks/include/MockShared.hpp"
15
+ #include "mocks/include/RTC/SCTP/association/MockAssociationListener.hpp"
16
+ #include "mocks/include/RTC/SCTP/tx/MockSendQueue.hpp"
17
+ #include <catch2/catch_test_macros.hpp>
18
+ #include <vector>
19
+
20
+ SCENARIO("SCTP RetransmissionQueue", "[sctp][retransmissionqueue]")
21
+ {
22
+ sctpCommon::ResetBuffers();
23
+
24
+ class MockRetransmissionQueueListener : public RTC::SCTP::RetransmissionQueue::Listener
25
+ {
26
+ public:
27
+ void OnRetransmissionQueueNewRttMs(uint64_t rttMs) override
28
+ {
29
+ this->lastRttMs = rttMs;
30
+ }
31
+
32
+ void OnRetransmissionQueueClearRetransmissionCounter() override
33
+ {
34
+ ++this->clearRetransmissionCounterCalls;
35
+ }
36
+
37
+ public:
38
+ uint64_t lastRttMs{ 0 };
39
+ size_t clearRetransmissionCounterCalls{ 0 };
40
+ };
41
+
42
+ class MockBackoffTimerHandleListener : public BackoffTimerHandleInterface::Listener
43
+ {
44
+ /* Pure virtual methods inherited from BackoffTimerHandleInterface::Listener. */
45
+ public:
46
+ void OnBackoffTimer(
47
+ BackoffTimerHandleInterface* /*backoffTimer*/, uint64_t& /*baseTimeoutMs*/, bool& /*stop*/) override
48
+ {
49
+ }
50
+ };
51
+
52
+ constexpr uint32_t Arwnd{ 100000 };
53
+ constexpr uint64_t Mtu{ 1191 };
54
+ // InitialTsn is the first TSN that will be assigned. The TSN before it
55
+ // (InitialTsn - 1) starts as ACKED in OutstandingData, matching dcsctp's
56
+ // invariant that the initial state has the previous TSN already
57
+ // cumulative-acked.
58
+ constexpr uint32_t InitialTsn{ 10 };
59
+
60
+ const RTC::SCTP::SctpOptions sctpOptions{ .mtu = Mtu };
61
+
62
+ MockRetransmissionQueueListener retransmissionQueueListener;
63
+ MockBackoffTimerHandleListener backoffTimerHandleListener;
64
+ mocks::RTC::SCTP::MockAssociationListener associationListener;
65
+ mocks::RTC::SCTP::MockSendQueue sendQueue;
66
+ uint64_t nowMs{ 10000 };
67
+ mocks::MockShared shared(/*getTimeMs*/
68
+ [&nowMs]()
69
+ {
70
+ return nowMs;
71
+ });
72
+
73
+ const std::unique_ptr<BackoffTimerHandleInterface> t3RtxTimerUniquePtr{ shared.CreateBackoffTimer(
74
+ BackoffTimerHandleInterface::BackoffTimerHandleOptions{
75
+ .listener = std::addressof(backoffTimerHandleListener),
76
+ .label = "mock-sctp-t3-rtx",
77
+ .baseTimeoutMs = sctpOptions.initialRtoMs,
78
+ .backoffAlgorithm = BackoffTimerHandleInterface::BackoffAlgorithm::EXPONENTIAL,
79
+ .maxBackoffTimeoutMs = sctpOptions.timerMaxBackoffTimeoutMs,
80
+ .maxRestarts = std::nullopt }) };
81
+
82
+ auto* t3RtxTimer = t3RtxTimerUniquePtr.get();
83
+
84
+ auto createRetransmissionQueue =
85
+ [&retransmissionQueueListener, &associationListener, &sendQueue, &t3RtxTimer, &sctpOptions](
86
+ bool supportsPartialReliability = true, bool useMessageInterleaving = false)
87
+ {
88
+ return RTC::SCTP::RetransmissionQueue(
89
+ std::addressof(retransmissionQueueListener),
90
+ associationListener,
91
+ InitialTsn,
92
+ Arwnd,
93
+ sendQueue,
94
+ t3RtxTimer,
95
+ sctpOptions,
96
+ supportsPartialReliability,
97
+ useMessageInterleaving);
98
+ };
99
+
100
+ auto createDataToSend = [](
101
+ uint32_t outgoingMessageId,
102
+ uint16_t maxRetransmissions = RTC::SCTP::Types::MaxRetransmitsNoLimit)
103
+ {
104
+ return [outgoingMessageId, maxRetransmissions](uint64_t /*nowMs*/, size_t /*maxLength*/)
105
+ {
106
+ RTC::SCTP::UserData data(
107
+ /*streamId*/ 1,
108
+ /*ssn*/ 0,
109
+ /*mid*/ 0,
110
+ /*fsn*/ 0,
111
+ /*ppid*/ 53,
112
+ /*payload*/ { 0x01, 0x02, 0x03, 0x04 },
113
+ /*isBeginning*/ true,
114
+ /*isEnd*/ true,
115
+ /*isUnordered*/ false);
116
+
117
+ RTC::SCTP::SendQueueInterface::DataToSend dataToSend(outgoingMessageId, std::move(data));
118
+
119
+ dataToSend.maxRetransmissions = maxRetransmissions;
120
+
121
+ return dataToSend;
122
+ };
123
+ };
124
+
125
+ auto createSackChunk = [sctpOptions](
126
+ uint32_t tsn,
127
+ uint32_t arwnd,
128
+ const std::vector<RTC::SCTP::SackChunk::GapAckBlock>&& gapAckBlocks = {})
129
+ {
130
+ std::unique_ptr<RTC::SCTP::SackChunk> chunk{ RTC::SCTP::SackChunk::Factory(
131
+ sctpCommon::FactoryBuffer, sctpOptions.mtu) };
132
+
133
+ chunk->SetCumulativeTsnAck(tsn);
134
+ chunk->SetAdvertisedReceiverWindowCredit(arwnd);
135
+
136
+ for (const auto& gapAckBlock : gapAckBlocks)
137
+ {
138
+ chunk->AddAckBlock(gapAckBlock);
139
+ }
140
+
141
+ return chunk;
142
+ };
143
+
144
+ auto getTSNsForFastRetransmit = [](RTC::SCTP::RetransmissionQueue& queue)
145
+ {
146
+ std::vector<uint32_t> tsns;
147
+
148
+ for (const auto& elem : queue.GetChunksForFastRetransmit(10000))
149
+ {
150
+ tsns.push_back(elem.first);
151
+ }
152
+
153
+ return tsns;
154
+ };
155
+
156
+ auto getSentPacketTSNs = [&nowMs](RTC::SCTP::RetransmissionQueue& queue, size_t maxLength = 10000)
157
+ {
158
+ std::vector<uint32_t> tsns;
159
+
160
+ for (const auto& elem : queue.GetChunksToSend(nowMs, maxLength))
161
+ {
162
+ tsns.push_back(elem.first);
163
+ }
164
+
165
+ return tsns;
166
+ };
167
+
168
+ SECTION("initial acked previous TSN")
169
+ {
170
+ auto retransmissionQueue = createRetransmissionQueue();
171
+
172
+ REQUIRE(retransmissionQueue.GetUnackedItems() == 0);
173
+ REQUIRE(retransmissionQueue.GetUnackedPacketBytes() == 0);
174
+ REQUIRE(retransmissionQueue.GetNextTsn() == InitialTsn);
175
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == false);
176
+ REQUIRE(
177
+ retransmissionQueue.GetChunkStatesForTesting() ==
178
+ std::vector<std::pair<uint32_t, RTC::SCTP::OutstandingData::State>>{
179
+ { InitialTsn - 1, RTC::SCTP::OutstandingData::State::ACKED },
180
+ });
181
+ }
182
+
183
+ SECTION("send one chunk")
184
+ {
185
+ auto retransmissionQueue = createRetransmissionQueue();
186
+
187
+ sendQueue.WillProduceOnce(createDataToSend(0))
188
+ .WillProduceRepeatedly(
189
+ [](uint64_t, size_t)
190
+ {
191
+ return std::nullopt;
192
+ });
193
+
194
+ REQUIRE(getSentPacketTSNs(retransmissionQueue) == std::vector<uint32_t>{ 10 });
195
+ REQUIRE(
196
+ retransmissionQueue.GetChunkStatesForTesting() ==
197
+ std::vector<std::pair<uint32_t, RTC::SCTP::OutstandingData::State>>{
198
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
199
+ { 10, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
200
+ });
201
+ }
202
+
203
+ SECTION("send one chunk and ack")
204
+ {
205
+ auto retransmissionQueue = createRetransmissionQueue();
206
+
207
+ sendQueue.WillProduceOnce(createDataToSend(0))
208
+ .WillProduceRepeatedly(
209
+ [](uint64_t, size_t)
210
+ {
211
+ return std::nullopt;
212
+ });
213
+
214
+ REQUIRE(getSentPacketTSNs(retransmissionQueue) == std::vector<uint32_t>{ 10 });
215
+
216
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(10, Arwnd).get());
217
+
218
+ REQUIRE(
219
+ retransmissionQueue.GetChunkStatesForTesting() ==
220
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
221
+ { 10, RTC::SCTP::OutstandingData::State::ACKED },
222
+ });
223
+ }
224
+
225
+ SECTION("send three chunks and ack two")
226
+ {
227
+ auto retransmissionQueue = createRetransmissionQueue();
228
+
229
+ sendQueue.WillProduceOnce(createDataToSend(0))
230
+ .WillProduceOnce(createDataToSend(1))
231
+ .WillProduceOnce(createDataToSend(2))
232
+ .WillProduceRepeatedly(
233
+ [](uint64_t, size_t)
234
+ {
235
+ return std::nullopt;
236
+ });
237
+
238
+ REQUIRE(getSentPacketTSNs(retransmissionQueue) == std::vector<uint32_t>{ 10, 11, 12 });
239
+
240
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(11, Arwnd).get());
241
+
242
+ REQUIRE(
243
+ retransmissionQueue.GetChunkStatesForTesting() ==
244
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
245
+ { 11, RTC::SCTP::OutstandingData::State::ACKED },
246
+ { 12, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
247
+ });
248
+ }
249
+
250
+ SECTION("ack with gap blocks from RFC 4960 section 334")
251
+ {
252
+ auto retransmissionQueue = createRetransmissionQueue();
253
+
254
+ sendQueue.WillProduceOnce(createDataToSend(0))
255
+ .WillProduceOnce(createDataToSend(1))
256
+ .WillProduceOnce(createDataToSend(2))
257
+ .WillProduceOnce(createDataToSend(3))
258
+ .WillProduceOnce(createDataToSend(4))
259
+ .WillProduceOnce(createDataToSend(5))
260
+ .WillProduceOnce(createDataToSend(6))
261
+ .WillProduceOnce(createDataToSend(7))
262
+ .WillProduceRepeatedly(
263
+ [](uint64_t, size_t)
264
+ {
265
+ return std::nullopt;
266
+ });
267
+
268
+ REQUIRE(
269
+ getSentPacketTSNs(retransmissionQueue) ==
270
+ std::vector<uint32_t>{ 10, 11, 12, 13, 14, 15, 16, 17 });
271
+
272
+ retransmissionQueue.HandleReceivedSackChunk(
273
+ nowMs,
274
+ createSackChunk(
275
+ 12,
276
+ Arwnd,
277
+ {
278
+ { 2, 3 },
279
+ { 5, 5 }
280
+ })
281
+ .get());
282
+
283
+ REQUIRE(
284
+ retransmissionQueue.GetChunkStatesForTesting() ==
285
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
286
+ { 12, RTC::SCTP::OutstandingData::State::ACKED },
287
+ { 13, RTC::SCTP::OutstandingData::State::NACKED },
288
+ { 14, RTC::SCTP::OutstandingData::State::ACKED },
289
+ { 15, RTC::SCTP::OutstandingData::State::ACKED },
290
+ { 16, RTC::SCTP::OutstandingData::State::NACKED },
291
+ { 17, RTC::SCTP::OutstandingData::State::ACKED },
292
+ });
293
+ }
294
+
295
+ SECTION("resend packet when nacked three times")
296
+ {
297
+ auto retransmissionQueue = createRetransmissionQueue();
298
+
299
+ sendQueue.WillProduceOnce(createDataToSend(0))
300
+ .WillProduceOnce(createDataToSend(1))
301
+ .WillProduceOnce(createDataToSend(2))
302
+ .WillProduceOnce(createDataToSend(3))
303
+ .WillProduceOnce(createDataToSend(4))
304
+ .WillProduceOnce(createDataToSend(5))
305
+ .WillProduceOnce(createDataToSend(6))
306
+ .WillProduceOnce(createDataToSend(7))
307
+ .WillProduceRepeatedly(
308
+ [](uint64_t, size_t)
309
+ {
310
+ return std::nullopt;
311
+ });
312
+
313
+ REQUIRE(
314
+ getSentPacketTSNs(retransmissionQueue) ==
315
+ std::vector<uint32_t>{ 10, 11, 12, 13, 14, 15, 16, 17 });
316
+
317
+ // Send more chunks, but leave some as gaps to force retransmission after
318
+ // three NACKs.
319
+
320
+ // Send TSN 18.
321
+ sendQueue.WillProduceOnce(createDataToSend(8))
322
+ .WillProduceRepeatedly(
323
+ [](uint64_t, size_t)
324
+ {
325
+ return std::nullopt;
326
+ });
327
+
328
+ REQUIRE(getSentPacketTSNs(retransmissionQueue) == std::vector<uint32_t>{ 18 });
329
+
330
+ // Ack 12, 14-15, 17-18.
331
+ retransmissionQueue.HandleReceivedSackChunk(
332
+ nowMs,
333
+ createSackChunk(
334
+ 12,
335
+ Arwnd,
336
+ {
337
+ { 2, 3 },
338
+ { 5, 6 }
339
+ })
340
+ .get());
341
+
342
+ REQUIRE(
343
+ retransmissionQueue.GetChunkStatesForTesting() ==
344
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
345
+ { 12, RTC::SCTP::OutstandingData::State::ACKED },
346
+ { 13, RTC::SCTP::OutstandingData::State::NACKED },
347
+ { 14, RTC::SCTP::OutstandingData::State::ACKED },
348
+ { 15, RTC::SCTP::OutstandingData::State::ACKED },
349
+ { 16, RTC::SCTP::OutstandingData::State::NACKED },
350
+ { 17, RTC::SCTP::OutstandingData::State::ACKED },
351
+ { 18, RTC::SCTP::OutstandingData::State::ACKED },
352
+ });
353
+
354
+ // Send TSN 19.
355
+ sendQueue.WillProduceOnce(createDataToSend(9))
356
+ .WillProduceRepeatedly(
357
+ [](uint64_t, size_t)
358
+ {
359
+ return std::nullopt;
360
+ });
361
+
362
+ REQUIRE(getSentPacketTSNs(retransmissionQueue) == std::vector<uint32_t>{ 19 });
363
+
364
+ // Ack 12, 14-15, 17-19.
365
+ retransmissionQueue.HandleReceivedSackChunk(
366
+ nowMs,
367
+ createSackChunk(
368
+ 12,
369
+ Arwnd,
370
+ {
371
+ { 2, 3 },
372
+ { 5, 7 }
373
+ })
374
+ .get());
375
+
376
+ // Send TSN 20.
377
+ sendQueue.WillProduceOnce(createDataToSend(10))
378
+ .WillProduceRepeatedly(
379
+ [](uint64_t, size_t)
380
+ {
381
+ return std::nullopt;
382
+ });
383
+
384
+ REQUIRE(getSentPacketTSNs(retransmissionQueue) == std::vector<uint32_t>{ 20 });
385
+
386
+ // Ack 12, 14-15, 17-20.
387
+ retransmissionQueue.HandleReceivedSackChunk(
388
+ nowMs,
389
+ createSackChunk(
390
+ 12,
391
+ Arwnd,
392
+ {
393
+ { 2, 3 },
394
+ { 5, 8 }
395
+ })
396
+ .get());
397
+
398
+ REQUIRE(
399
+ retransmissionQueue.GetChunkStatesForTesting() ==
400
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
401
+ { 12, RTC::SCTP::OutstandingData::State::ACKED },
402
+ { 13, RTC::SCTP::OutstandingData::State::TO_BE_RETRANSMITTED },
403
+ { 14, RTC::SCTP::OutstandingData::State::ACKED },
404
+ { 15, RTC::SCTP::OutstandingData::State::ACKED },
405
+ { 16, RTC::SCTP::OutstandingData::State::TO_BE_RETRANSMITTED },
406
+ { 17, RTC::SCTP::OutstandingData::State::ACKED },
407
+ { 18, RTC::SCTP::OutstandingData::State::ACKED },
408
+ { 19, RTC::SCTP::OutstandingData::State::ACKED },
409
+ { 20, RTC::SCTP::OutstandingData::State::ACKED },
410
+ });
411
+
412
+ // This will trigger "fast retransmit" mode and only chunks 13 and 16 will
413
+ // be resent right now. The send queue will not even be queried.
414
+ sendQueue.ExpectProduceCalledTimes(0);
415
+
416
+ REQUIRE(getTSNsForFastRetransmit(retransmissionQueue) == std::vector<uint32_t>{ 13, 16 });
417
+ REQUIRE(
418
+ retransmissionQueue.GetChunkStatesForTesting() ==
419
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
420
+ { 12, RTC::SCTP::OutstandingData::State::ACKED },
421
+ { 13, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
422
+ { 14, RTC::SCTP::OutstandingData::State::ACKED },
423
+ { 15, RTC::SCTP::OutstandingData::State::ACKED },
424
+ { 16, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
425
+ { 17, RTC::SCTP::OutstandingData::State::ACKED },
426
+ { 18, RTC::SCTP::OutstandingData::State::ACKED },
427
+ { 19, RTC::SCTP::OutstandingData::State::ACKED },
428
+ { 20, RTC::SCTP::OutstandingData::State::ACKED },
429
+ });
430
+ REQUIRE_VERIFICATION_RESULT(sendQueue.VerifyExpectations());
431
+ }
432
+
433
+ SECTION("restarts T3-rtx timer on retransmit first outstanding TSN")
434
+ {
435
+ auto retransmissionQueue = createRetransmissionQueue();
436
+
437
+ sendQueue.WillProduceOnce(createDataToSend(0))
438
+ .WillProduceOnce(createDataToSend(1))
439
+ .WillProduceOnce(createDataToSend(2))
440
+ .WillProduceRepeatedly(
441
+ [](uint64_t, size_t)
442
+ {
443
+ return std::nullopt;
444
+ });
445
+
446
+ // Starting time.
447
+ nowMs = 100 * 1000; // 100 seconds.
448
+
449
+ REQUIRE(getSentPacketTSNs(retransmissionQueue) == std::vector<uint32_t>{ 10, 11, 12 });
450
+
451
+ // Ack 10, 12, after 100ms.
452
+ nowMs += 100;
453
+
454
+ retransmissionQueue.HandleReceivedSackChunk(
455
+ nowMs,
456
+ createSackChunk(
457
+ 10,
458
+ Arwnd,
459
+ {
460
+ { 2, 2 },
461
+ })
462
+ .get());
463
+
464
+ REQUIRE(
465
+ retransmissionQueue.GetChunkStatesForTesting() ==
466
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
467
+ { 10, RTC::SCTP::OutstandingData::State::ACKED },
468
+ { 11, RTC::SCTP::OutstandingData::State::NACKED },
469
+ { 12, RTC::SCTP::OutstandingData::State::ACKED },
470
+ });
471
+
472
+ // Send 13.
473
+ sendQueue.WillProduceOnce(createDataToSend(3))
474
+ .WillProduceRepeatedly(
475
+ [](uint64_t, size_t)
476
+ {
477
+ return std::nullopt;
478
+ });
479
+
480
+ REQUIRE(getSentPacketTSNs(retransmissionQueue) == std::vector<uint32_t>{ 13 });
481
+
482
+ // Ack 10, 12-13, after 100ms.
483
+ nowMs += 100;
484
+
485
+ retransmissionQueue.HandleReceivedSackChunk(
486
+ nowMs,
487
+ createSackChunk(
488
+ 10,
489
+ Arwnd,
490
+ {
491
+ { 2, 3 },
492
+ })
493
+ .get());
494
+
495
+ // Send 14.
496
+ sendQueue.WillProduceOnce(createDataToSend(4))
497
+ .WillProduceRepeatedly(
498
+ [](uint64_t, size_t)
499
+ {
500
+ return std::nullopt;
501
+ });
502
+
503
+ REQUIRE(getSentPacketTSNs(retransmissionQueue) == std::vector<uint32_t>{ 14 });
504
+
505
+ // Ack 10, 12-14, after 100 ms.
506
+ nowMs += 100;
507
+
508
+ retransmissionQueue.HandleReceivedSackChunk(
509
+ nowMs,
510
+ createSackChunk(
511
+ 10,
512
+ Arwnd,
513
+ {
514
+ { 2, 4 },
515
+ })
516
+ .get());
517
+
518
+ REQUIRE(
519
+ retransmissionQueue.GetChunkStatesForTesting() ==
520
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
521
+ { 10, RTC::SCTP::OutstandingData::State::ACKED },
522
+ { 11, RTC::SCTP::OutstandingData::State::TO_BE_RETRANSMITTED },
523
+ { 12, RTC::SCTP::OutstandingData::State::ACKED },
524
+ { 13, RTC::SCTP::OutstandingData::State::ACKED },
525
+ { 14, RTC::SCTP::OutstandingData::State::ACKED },
526
+ });
527
+
528
+ // This will trigger "fast retransmit" mode and only chunks 13 and 16 will
529
+ // be resent right now. The send queue will not even be queried.
530
+ sendQueue.ExpectProduceCalledTimes(0);
531
+
532
+ REQUIRE(getTSNsForFastRetransmit(retransmissionQueue) == std::vector<uint32_t>{ 11 });
533
+
534
+ REQUIRE(
535
+ retransmissionQueue.GetChunkStatesForTesting() ==
536
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
537
+ { 10, RTC::SCTP::OutstandingData::State::ACKED },
538
+ { 11, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
539
+ { 12, RTC::SCTP::OutstandingData::State::ACKED },
540
+ { 13, RTC::SCTP::OutstandingData::State::ACKED },
541
+ { 14, RTC::SCTP::OutstandingData::State::ACKED },
542
+ });
543
+
544
+ // Verify that the timer was really restarted when fast-retransmitting. The
545
+ // timeout is `sctpOptions.initialRtoMs`, so advance the time just before
546
+ // that.
547
+ nowMs += (sctpOptions.initialRtoMs - 1);
548
+
549
+ auto* backoffTimer = shared.GetBackoffTimer("mock-sctp-t3-rtx");
550
+
551
+ REQUIRE(backoffTimer);
552
+ REQUIRE(backoffTimer->EvaluateHasExpired() == false);
553
+
554
+ nowMs += 1;
555
+
556
+ REQUIRE(backoffTimer->EvaluateHasExpired() == true);
557
+ }
558
+
559
+ SECTION("can only produce two packets but wants to send three")
560
+ {
561
+ auto retransmissionQueue = createRetransmissionQueue();
562
+
563
+ sendQueue.WillProduceOnce(createDataToSend(0))
564
+ .WillProduceOnce(createDataToSend(1))
565
+ .WillProduceRepeatedly(
566
+ [](uint64_t, size_t)
567
+ {
568
+ return std::nullopt;
569
+ });
570
+
571
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, 1000) == std::vector<uint32_t>{ 10, 11 });
572
+ REQUIRE(
573
+ retransmissionQueue.GetChunkStatesForTesting() ==
574
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
575
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
576
+ { 10, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
577
+ { 11, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
578
+ });
579
+ }
580
+
581
+ SECTION("retransmits on T3-rtx expiry")
582
+ {
583
+ auto retransmissionQueue = createRetransmissionQueue();
584
+
585
+ sendQueue.WillProduceOnce(createDataToSend(0))
586
+ .WillProduceRepeatedly(
587
+ [](uint64_t, size_t)
588
+ {
589
+ return std::nullopt;
590
+ });
591
+
592
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == false);
593
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, 1000) == std::vector<uint32_t>{ 10 });
594
+ REQUIRE(
595
+ retransmissionQueue.GetChunkStatesForTesting() ==
596
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
597
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
598
+ { 10, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
599
+ });
600
+
601
+ // Will force chunks to be retransmitted.
602
+ retransmissionQueue.HandleT3RtxTimerExpiry();
603
+
604
+ REQUIRE(
605
+ retransmissionQueue.GetChunkStatesForTesting() ==
606
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
607
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
608
+ { 10, RTC::SCTP::OutstandingData::State::TO_BE_RETRANSMITTED },
609
+ });
610
+
611
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == false);
612
+
613
+ REQUIRE(
614
+ retransmissionQueue.GetChunkStatesForTesting() ==
615
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
616
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
617
+ { 10, RTC::SCTP::OutstandingData::State::TO_BE_RETRANSMITTED },
618
+ });
619
+
620
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, 1000) == std::vector<uint32_t>{ 10 });
621
+ REQUIRE(
622
+ retransmissionQueue.GetChunkStatesForTesting() ==
623
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
624
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
625
+ { 10, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
626
+ });
627
+ }
628
+
629
+ SECTION("limited retransmission only with RFC 3758 support")
630
+ {
631
+ auto retransmissionQueue = createRetransmissionQueue(/*supportsPartialReliability*/ false);
632
+
633
+ sendQueue.WillProduceOnce(createDataToSend(42, /*maxRetransmissions*/ 0))
634
+ .WillProduceRepeatedly(
635
+ [](uint64_t, size_t)
636
+ {
637
+ return std::nullopt;
638
+ });
639
+
640
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == false);
641
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, 1000) == std::vector<uint32_t>{ 10 });
642
+ REQUIRE(
643
+ retransmissionQueue.GetChunkStatesForTesting() ==
644
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
645
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
646
+ { 10, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
647
+ });
648
+
649
+ // Will force chunks to be retransmitted.
650
+ retransmissionQueue.HandleT3RtxTimerExpiry();
651
+
652
+ REQUIRE(
653
+ retransmissionQueue.GetChunkStatesForTesting() ==
654
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
655
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
656
+ { 10, RTC::SCTP::OutstandingData::State::TO_BE_RETRANSMITTED },
657
+ });
658
+
659
+ // Discard must NOT be called.
660
+ sendQueue.ExpectDiscardCalledTimes(0);
661
+
662
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == false);
663
+ REQUIRE_VERIFICATION_RESULT(sendQueue.VerifyExpectations());
664
+ }
665
+
666
+ SECTION("limits retransmissions as UDP")
667
+ {
668
+ auto retransmissionQueue = createRetransmissionQueue();
669
+
670
+ sendQueue.WillProduceOnce(createDataToSend(42, /*maxRetransmissions*/ 0))
671
+ .WillProduceRepeatedly(
672
+ [](uint64_t, size_t)
673
+ {
674
+ return std::nullopt;
675
+ });
676
+
677
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == false);
678
+
679
+ REQUIRE(getSentPacketTSNs(retransmissionQueue) == std::vector<uint32_t>{ 10 });
680
+ REQUIRE(
681
+ retransmissionQueue.GetChunkStatesForTesting() ==
682
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
683
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
684
+ { 10, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
685
+ });
686
+
687
+ // Will force chunks to be retransmitted (abandoned because
688
+ // `maxRetransmissions: 0`).
689
+ sendQueue.WillDiscardOnce(1, 42, /*returnValue*/ false);
690
+
691
+ retransmissionQueue.HandleT3RtxTimerExpiry();
692
+
693
+ REQUIRE(
694
+ retransmissionQueue.GetChunkStatesForTesting() ==
695
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
696
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
697
+ { 10, RTC::SCTP::OutstandingData::State::ABANDONED },
698
+ });
699
+
700
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == true);
701
+
702
+ REQUIRE(
703
+ retransmissionQueue.GetChunkStatesForTesting() ==
704
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
705
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
706
+ { 10, RTC::SCTP::OutstandingData::State::ABANDONED },
707
+ });
708
+
709
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, 1000).empty());
710
+ REQUIRE(
711
+ retransmissionQueue.GetChunkStatesForTesting() ==
712
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
713
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
714
+ { 10, RTC::SCTP::OutstandingData::State::ABANDONED },
715
+ });
716
+ }
717
+
718
+ SECTION("limits retransmissions to three sends")
719
+ {
720
+ auto retransmissionQueue = createRetransmissionQueue();
721
+
722
+ sendQueue.WillProduceOnce(createDataToSend(42, /*maxRetransmissions*/ 3))
723
+ .WillProduceRepeatedly(
724
+ [](uint64_t, size_t)
725
+ {
726
+ return std::nullopt;
727
+ });
728
+
729
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == false);
730
+
731
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, 1000) == std::vector<uint32_t>{ 10 });
732
+ REQUIRE(
733
+ retransmissionQueue.GetChunkStatesForTesting() ==
734
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
735
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
736
+ { 10, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
737
+ });
738
+
739
+ // `Discard()` must NOT be called for the first three retransmissions.
740
+ sendQueue.ExpectDiscardCalledTimes(0);
741
+
742
+ // Retransmission 1.
743
+ retransmissionQueue.HandleT3RtxTimerExpiry();
744
+
745
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == false);
746
+ REQUIRE(retransmissionQueue.GetChunksToSend(nowMs, 1000).size() == 1);
747
+
748
+ // Retransmission 2.
749
+ retransmissionQueue.HandleT3RtxTimerExpiry();
750
+
751
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == false);
752
+ REQUIRE(retransmissionQueue.GetChunksToSend(nowMs, 1000).size() == 1);
753
+
754
+ // Retransmission 3.
755
+ retransmissionQueue.HandleT3RtxTimerExpiry();
756
+
757
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == false);
758
+ REQUIRE(retransmissionQueue.GetChunksToSend(nowMs, 1000).size() == 1);
759
+
760
+ REQUIRE_VERIFICATION_RESULT(sendQueue.VerifyExpectations());
761
+
762
+ // Retransmission 4. Not allowed, chunk is abandoned.
763
+ sendQueue.WillDiscardOnce(1, 42, /*returnValue*/ false);
764
+
765
+ retransmissionQueue.HandleT3RtxTimerExpiry();
766
+
767
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == true);
768
+ REQUIRE(retransmissionQueue.GetChunksToSend(nowMs, 1000).empty());
769
+
770
+ REQUIRE(
771
+ retransmissionQueue.GetChunkStatesForTesting() ==
772
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
773
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
774
+ { 10, RTC::SCTP::OutstandingData::State::ABANDONED },
775
+ });
776
+ }
777
+
778
+ SECTION("retransmits when send buffer is full on T3-rtx expiry")
779
+ {
780
+ auto retransmissionQueue = createRetransmissionQueue();
781
+
782
+ constexpr size_t Cwnd{ 1200 };
783
+
784
+ retransmissionQueue.SetCwnd(Cwnd);
785
+
786
+ REQUIRE(retransmissionQueue.GetCwnd() == Cwnd);
787
+ REQUIRE(retransmissionQueue.GetUnackedPacketBytes() == 0);
788
+ REQUIRE(retransmissionQueue.GetUnackedItems() == 0);
789
+
790
+ const std::vector<uint8_t> payload(1000, 0x00);
791
+
792
+ sendQueue
793
+ .WillProduceOnce(
794
+ [&payload](uint64_t /*nowMs*/, size_t /*maxLength*/)
795
+ {
796
+ return RTC::SCTP::SendQueueInterface::DataToSend(
797
+ 0, RTC::SCTP::UserData(1, 0, 0, 0, 53, payload, true, true, false));
798
+ })
799
+ .WillProduceRepeatedly(
800
+ [](uint64_t, size_t)
801
+ {
802
+ return std::nullopt;
803
+ });
804
+
805
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, 1500) == std::vector<uint32_t>{ 10 });
806
+ REQUIRE(
807
+ retransmissionQueue.GetChunkStatesForTesting() ==
808
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
809
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
810
+ { 10, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
811
+ });
812
+ REQUIRE(
813
+ retransmissionQueue.GetUnackedPacketBytes() ==
814
+ payload.size() + RTC::SCTP::DataChunk::DataChunkHeaderLength);
815
+ REQUIRE(retransmissionQueue.GetUnackedItems() == 1);
816
+
817
+ // Will force chunks to be retransmitted.
818
+ retransmissionQueue.HandleT3RtxTimerExpiry();
819
+
820
+ REQUIRE(
821
+ retransmissionQueue.GetChunkStatesForTesting() ==
822
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
823
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
824
+ { 10, RTC::SCTP::OutstandingData::State::TO_BE_RETRANSMITTED },
825
+ });
826
+
827
+ // After T3 expiry in-flight counters are cleared.
828
+ REQUIRE(retransmissionQueue.GetUnackedPacketBytes() == 0);
829
+ REQUIRE(retransmissionQueue.GetUnackedItems() == 0);
830
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, 1500) == std::vector<uint32_t>{ 10 });
831
+ REQUIRE(
832
+ retransmissionQueue.GetChunkStatesForTesting() ==
833
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
834
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
835
+ { 10, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
836
+ });
837
+ REQUIRE(
838
+ retransmissionQueue.GetUnackedPacketBytes() ==
839
+ payload.size() + RTC::SCTP::DataChunk::DataChunkHeaderLength);
840
+ REQUIRE(retransmissionQueue.GetUnackedItems() == 1);
841
+ }
842
+
843
+ SECTION("produces valid FORWARD-TSN")
844
+ {
845
+ // Three middle fragments (no "E"), same message (outgoingMessageId=42,
846
+ // ssn=42). `Discard()` returns true, placeholder TSN 13 created.
847
+ // FORWARD-TSN newCumulativeTsn=13, skippedStreams={ (streamId=1, ssn=42) }.
848
+
849
+ auto retransmissionQueue = createRetransmissionQueue();
850
+
851
+ // "B" — beginning.
852
+ sendQueue
853
+ .WillProduceOnce(
854
+ [](uint64_t /*nowMs*/, size_t /*maxLength*/)
855
+ {
856
+ RTC::SCTP::UserData data(1, 42, 0, 0, 53, { 0x01, 0x02, 0x03, 0x04 }, true, false, false);
857
+ RTC::SCTP::SendQueueInterface::DataToSend dataToSend(42, std::move(data));
858
+
859
+ dataToSend.maxRetransmissions = 0;
860
+
861
+ return dataToSend;
862
+ })
863
+ // Middle fragment.
864
+ .WillProduceOnce(
865
+ [](uint64_t /*nowMs*/, size_t /*maxLength*/)
866
+ {
867
+ RTC::SCTP::UserData data(1, 42, 0, 0, 53, { 0x05, 0x06, 0x07, 0x08 }, false, false, false);
868
+ RTC::SCTP::SendQueueInterface::DataToSend dataToSend(42, std::move(data));
869
+
870
+ dataToSend.maxRetransmissions = 0;
871
+
872
+ return dataToSend;
873
+ })
874
+ // Another middle fragment (message not fully sent — no "E").
875
+ .WillProduceOnce(
876
+ [](uint64_t /*nowMs*/, size_t /*maxLength*/)
877
+ {
878
+ RTC::SCTP::UserData data(1, 42, 0, 0, 53, { 0x09, 0x0a, 0x0b, 0x0c }, false, false, false);
879
+ RTC::SCTP::SendQueueInterface::DataToSend dataToSend(42, std::move(data));
880
+
881
+ dataToSend.maxRetransmissions = 0;
882
+
883
+ return dataToSend;
884
+ })
885
+ .WillProduceRepeatedly(
886
+ [](uint64_t, size_t)
887
+ {
888
+ return std::nullopt;
889
+ });
890
+
891
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, 1000) == std::vector<uint32_t>{ 10, 11, 12 });
892
+ REQUIRE(
893
+ retransmissionQueue.GetChunkStatesForTesting() ==
894
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
895
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
896
+ { 10, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
897
+ { 11, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
898
+ { 12, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
899
+ });
900
+
901
+ // Ack TSN 10, but the remaining are lost.
902
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(10, Arwnd).get());
903
+
904
+ // T3 expiry: TSN 11, 12 abandoned. `Discard()` returns true, placeholder TSN 13.
905
+ sendQueue.WillDiscardOnce(1, 42, /*returnValue*/ true);
906
+
907
+ retransmissionQueue.HandleT3RtxTimerExpiry();
908
+
909
+ // NOTE: TSN 13 represents the placeholder end fragment.
910
+ REQUIRE(
911
+ retransmissionQueue.GetChunkStatesForTesting() ==
912
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
913
+ { 10, RTC::SCTP::OutstandingData::State::ACKED },
914
+ { 11, RTC::SCTP::OutstandingData::State::ABANDONED },
915
+ { 12, RTC::SCTP::OutstandingData::State::ABANDONED },
916
+ { 13, RTC::SCTP::OutstandingData::State::ABANDONED },
917
+ });
918
+
919
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == true);
920
+
921
+ const std::unique_ptr<RTC::SCTP::Packet> packet{ RTC::SCTP::Packet::Factory(
922
+ sctpCommon::FactoryBuffer, sctpOptions.mtu) };
923
+ const auto* forwardTsnChunk = retransmissionQueue.AddForwardTsn(packet.get());
924
+
925
+ REQUIRE(forwardTsnChunk);
926
+ REQUIRE(forwardTsnChunk->GetNewCumulativeTsn() == 13);
927
+ REQUIRE(
928
+ forwardTsnChunk->GetSkippedStreams() ==
929
+ std::vector<RTC::SCTP::AnyForwardTsnChunk::SkippedStream>{
930
+ { 1, 42 }
931
+ });
932
+ }
933
+
934
+ SECTION("produces valid FORWARD-TSN when fully sent")
935
+ {
936
+ // Three fragments "B"/""/""E" (message fully sent). `Discard()` returns
937
+ // false, no placeholder. FORWARD-TSN newCumulativeTsn=12.
938
+
939
+ auto retransmissionQueue = createRetransmissionQueue();
940
+
941
+ sendQueue
942
+ .WillProduceOnce(
943
+ [](uint64_t /*nowMs*/, size_t /*maxLength*/)
944
+ {
945
+ RTC::SCTP::UserData data(1, 42, 0, 0, 53, { 0x01, 0x02, 0x03, 0x04 }, true, false, false);
946
+ RTC::SCTP::SendQueueInterface::DataToSend dataToSend(42, std::move(data));
947
+
948
+ dataToSend.maxRetransmissions = 0;
949
+
950
+ return dataToSend;
951
+ })
952
+ .WillProduceOnce(
953
+ [](uint64_t /*nowMs*/, size_t /*maxLength*/)
954
+ {
955
+ RTC::SCTP::UserData data(1, 42, 0, 0, 53, { 0x05, 0x06, 0x07, 0x08 }, false, false, false);
956
+ RTC::SCTP::SendQueueInterface::DataToSend dataToSend(42, std::move(data));
957
+
958
+ dataToSend.maxRetransmissions = 0;
959
+
960
+ return dataToSend;
961
+ })
962
+ // "E" — end fragment (message fully sent).
963
+ .WillProduceOnce(
964
+ [](uint64_t /*nowMs*/, size_t /*maxLength*/)
965
+ {
966
+ RTC::SCTP::UserData data(1, 42, 0, 0, 53, { 0x09, 0x0a, 0x0b, 0x0c }, false, true, false);
967
+ RTC::SCTP::SendQueueInterface::DataToSend dataToSend(42, std::move(data));
968
+
969
+ dataToSend.maxRetransmissions = 0;
970
+
971
+ return dataToSend;
972
+ })
973
+ .WillProduceRepeatedly(
974
+ [](uint64_t, size_t)
975
+ {
976
+ return std::nullopt;
977
+ });
978
+
979
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, 1000) == std::vector<uint32_t>{ 10, 11, 12 });
980
+ REQUIRE(
981
+ retransmissionQueue.GetChunkStatesForTesting() ==
982
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
983
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
984
+ { 10, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
985
+ { 11, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
986
+ { 12, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
987
+ });
988
+
989
+ // Ack TSN 10, but the remaining are lost.
990
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(10, Arwnd).get());
991
+
992
+ // T3 expiry: TSN 11, 12 abandoned. `Discard()` returns false, no placeholder.
993
+ sendQueue.WillDiscardOnce(1, 42, /*returnValue*/ false);
994
+
995
+ retransmissionQueue.HandleT3RtxTimerExpiry();
996
+
997
+ REQUIRE(
998
+ retransmissionQueue.GetChunkStatesForTesting() ==
999
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
1000
+ { 10, RTC::SCTP::OutstandingData::State::ACKED },
1001
+ { 11, RTC::SCTP::OutstandingData::State::ABANDONED },
1002
+ { 12, RTC::SCTP::OutstandingData::State::ABANDONED },
1003
+ });
1004
+
1005
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == true);
1006
+
1007
+ const std::unique_ptr<RTC::SCTP::Packet> packet{ RTC::SCTP::Packet::Factory(
1008
+ sctpCommon::FactoryBuffer, sctpOptions.mtu) };
1009
+ const auto* forwardTsnChunk = retransmissionQueue.AddForwardTsn(packet.get());
1010
+
1011
+ REQUIRE(forwardTsnChunk);
1012
+ REQUIRE(forwardTsnChunk->GetNewCumulativeTsn() == 12);
1013
+ REQUIRE(
1014
+ forwardTsnChunk->GetSkippedStreams() ==
1015
+ std::vector<RTC::SCTP::AnyForwardTsnChunk::SkippedStream>{
1016
+ { 1, 42 }
1017
+ });
1018
+ }
1019
+
1020
+ SECTION("produces valid I-FORWARD-TSN")
1021
+ {
1022
+ auto retransmissionQueue = createRetransmissionQueue(
1023
+ /*supportsPartialReliability*/ true, /*useMessageInterleaving*/ true);
1024
+
1025
+ // Stream 1, ordered, outgoingMessageId=42, mid=42, "B".
1026
+ sendQueue
1027
+ .WillProduceOnce(
1028
+ [](uint64_t /*nowMs*/, size_t /*maxLength*/)
1029
+ {
1030
+ RTC::SCTP::UserData data(1, 0, 42, 0, 53, { 0x01, 0x02, 0x03, 0x04 }, true, false, false);
1031
+ RTC::SCTP::SendQueueInterface::DataToSend dataToSend(42, std::move(data));
1032
+
1033
+ dataToSend.maxRetransmissions = 0;
1034
+
1035
+ return dataToSend;
1036
+ })
1037
+ // Stream 2, unordered, outgoingMessageId=43, mid=42, "B".
1038
+ .WillProduceOnce(
1039
+ [](uint64_t /*nowMs*/, size_t /*maxLength*/)
1040
+ {
1041
+ RTC::SCTP::UserData data(2, 0, 42, 0, 53, { 0x01, 0x02, 0x03, 0x04 }, true, false, true);
1042
+ RTC::SCTP::SendQueueInterface::DataToSend dataToSend(43, std::move(data));
1043
+
1044
+ dataToSend.maxRetransmissions = 0;
1045
+
1046
+ return dataToSend;
1047
+ })
1048
+ // Stream 3, ordered, outgoingMessageId=44, mid=42, "B".
1049
+ .WillProduceOnce(
1050
+ [](uint64_t /*nowMs*/, size_t /*maxLength*/)
1051
+ {
1052
+ RTC::SCTP::UserData data(3, 0, 42, 0, 53, { 0x09, 0x0a, 0x0b, 0x0c }, true, false, false);
1053
+ RTC::SCTP::SendQueueInterface::DataToSend dataToSend(44, std::move(data));
1054
+
1055
+ dataToSend.maxRetransmissions = 0;
1056
+
1057
+ return dataToSend;
1058
+ })
1059
+ // Stream 4, ordered, outgoingMessageId=45, mid=42, "B".
1060
+ .WillProduceOnce(
1061
+ [](uint64_t /*nowMs*/, size_t /*maxLength*/)
1062
+ {
1063
+ RTC::SCTP::UserData data(4, 0, 42, 0, 53, { 0x0d, 0x0e, 0x0f, 0x10 }, true, false, false);
1064
+ RTC::SCTP::SendQueueInterface::DataToSend dataToSend(45, std::move(data));
1065
+
1066
+ dataToSend.maxRetransmissions = 0;
1067
+
1068
+ return dataToSend;
1069
+ })
1070
+ .WillProduceRepeatedly(
1071
+ [](uint64_t, size_t)
1072
+ {
1073
+ return std::nullopt;
1074
+ });
1075
+
1076
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, 1000) == std::vector<uint32_t>{ 10, 11, 12, 13 });
1077
+ REQUIRE(
1078
+ retransmissionQueue.GetChunkStatesForTesting() ==
1079
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
1080
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
1081
+ { 10, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1082
+ { 11, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1083
+ { 12, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1084
+ { 13, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1085
+ });
1086
+
1087
+ // TSN 13 is acked via gap block; TSN 10-12 are nacked.
1088
+ retransmissionQueue.HandleReceivedSackChunk(
1089
+ nowMs,
1090
+ createSackChunk(
1091
+ 9,
1092
+ Arwnd,
1093
+ {
1094
+ { 4, 4 },
1095
+ })
1096
+ .get());
1097
+
1098
+ REQUIRE(
1099
+ retransmissionQueue.GetChunkStatesForTesting() ==
1100
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
1101
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
1102
+ { 10, RTC::SCTP::OutstandingData::State::NACKED },
1103
+ { 11, RTC::SCTP::OutstandingData::State::NACKED },
1104
+ { 12, RTC::SCTP::OutstandingData::State::NACKED },
1105
+ { 13, RTC::SCTP::OutstandingData::State::ACKED },
1106
+ });
1107
+
1108
+ // T3 expiry: TSN 10-12 abandoned. `Discard()` called 3 times (one per stream),
1109
+ // each returns true, placeholder TSNs 14, 15, 16.
1110
+ sendQueue.WillDiscardOnce(1, 42, /*returnValue*/ true);
1111
+ sendQueue.WillDiscardOnce(2, 43, /*returnValue*/ true);
1112
+ sendQueue.WillDiscardOnce(3, 44, /*returnValue*/ true);
1113
+
1114
+ retransmissionQueue.HandleT3RtxTimerExpiry();
1115
+
1116
+ REQUIRE(
1117
+ retransmissionQueue.GetChunkStatesForTesting() ==
1118
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
1119
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
1120
+ { 10, RTC::SCTP::OutstandingData::State::ABANDONED },
1121
+ { 11, RTC::SCTP::OutstandingData::State::ABANDONED },
1122
+ { 12, RTC::SCTP::OutstandingData::State::ABANDONED },
1123
+ { 13, RTC::SCTP::OutstandingData::State::ACKED },
1124
+ // Placeholder end fragments for streams 1, 2 and 3.
1125
+ { 14, RTC::SCTP::OutstandingData::State::ABANDONED },
1126
+ { 15, RTC::SCTP::OutstandingData::State::ABANDONED },
1127
+ { 16, RTC::SCTP::OutstandingData::State::ABANDONED },
1128
+ });
1129
+
1130
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == true);
1131
+
1132
+ // I-FORWARD-TSN: newCumulativeTsn=12 (can't go past ACKED TSN 13).
1133
+ std::unique_ptr<RTC::SCTP::Packet> packet{ RTC::SCTP::Packet::Factory(
1134
+ sctpCommon::FactoryBuffer, sctpOptions.mtu) };
1135
+
1136
+ const auto* iForwardTsnChunk1 = retransmissionQueue.AddIForwardTsn(packet.get());
1137
+
1138
+ REQUIRE(iForwardTsnChunk1);
1139
+ REQUIRE(iForwardTsnChunk1->GetNewCumulativeTsn() == 12);
1140
+ REQUIRE(
1141
+ iForwardTsnChunk1->GetSkippedStreams() ==
1142
+ std::vector<RTC::SCTP::AnyForwardTsnChunk::SkippedStream>{
1143
+ { false, 1, 42 },
1144
+ { false, 3, 42 },
1145
+ { true, 2, 42 },
1146
+ });
1147
+
1148
+ // When TSN 13 is acked, the placeholder end fragments must be skipped too.
1149
+ // A receiver is more likely to ack TSN 13, but do it incrementally.
1150
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(12, Arwnd).get());
1151
+
1152
+ sendQueue.ExpectDiscardCalledTimes(0);
1153
+
1154
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == false);
1155
+ REQUIRE_VERIFICATION_RESULT(sendQueue.VerifyExpectations());
1156
+
1157
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(13, Arwnd).get());
1158
+
1159
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == true);
1160
+
1161
+ REQUIRE(
1162
+ retransmissionQueue.GetChunkStatesForTesting() ==
1163
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
1164
+ { 13, RTC::SCTP::OutstandingData::State::ACKED },
1165
+ { 14, RTC::SCTP::OutstandingData::State::ABANDONED },
1166
+ { 15, RTC::SCTP::OutstandingData::State::ABANDONED },
1167
+ { 16, RTC::SCTP::OutstandingData::State::ABANDONED },
1168
+ });
1169
+
1170
+ packet.reset(RTC::SCTP::Packet::Factory(sctpCommon::FactoryBuffer, sctpOptions.mtu));
1171
+
1172
+ const auto* iForwardTsnChunk2 = retransmissionQueue.AddIForwardTsn(packet.get());
1173
+
1174
+ REQUIRE(iForwardTsnChunk2);
1175
+ REQUIRE(iForwardTsnChunk2->GetNewCumulativeTsn() == 16);
1176
+ REQUIRE(
1177
+ iForwardTsnChunk2->GetSkippedStreams() ==
1178
+ std::vector<RTC::SCTP::AnyForwardTsnChunk::SkippedStream>{
1179
+ { false, 1, 42 },
1180
+ { false, 3, 42 },
1181
+ { true, 2, 42 },
1182
+ });
1183
+ }
1184
+
1185
+ SECTION("measure RTT")
1186
+ {
1187
+ auto retransmissionQueue = createRetransmissionQueue(
1188
+ /*supportsPartialReliability*/ true, /*useMessageInterleaving*/ true);
1189
+
1190
+ sendQueue.WillProduceOnce(createDataToSend(0, /*maxRetranmissions*/ 0))
1191
+ .WillProduceRepeatedly(
1192
+ [](uint64_t, size_t)
1193
+ {
1194
+ return std::nullopt;
1195
+ });
1196
+
1197
+ REQUIRE(getSentPacketTSNs(retransmissionQueue) == std::vector<uint32_t>{ 10 });
1198
+
1199
+ constexpr uint64_t DurationMs{ 123 };
1200
+
1201
+ nowMs += DurationMs;
1202
+
1203
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(10, Arwnd).get());
1204
+
1205
+ REQUIRE(retransmissionQueueListener.lastRttMs == DurationMs);
1206
+ }
1207
+
1208
+ SECTION("validate cumulative TSN at rest")
1209
+ {
1210
+ // Nothing outstanding. TSN 8 is below lastCumulativeTsnAck(9) -> rejected.
1211
+ // TSN 9 equals lastCumulativeTsnAck(9) -> accepted (no-op).
1212
+ // TSN 10 is above highestOutstandingTsn(9) -> rejected.
1213
+
1214
+ auto retransmissionQueue = createRetransmissionQueue();
1215
+
1216
+ REQUIRE(
1217
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(8, Arwnd).get()) == false);
1218
+ REQUIRE(
1219
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(9, Arwnd).get()) == true);
1220
+ REQUIRE(
1221
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(10, Arwnd).get()) == false);
1222
+ }
1223
+
1224
+ SECTION("validate cumulative TSN ack on inflight data")
1225
+ {
1226
+ auto retransmissionQueue = createRetransmissionQueue();
1227
+
1228
+ sendQueue.WillProduceOnce(createDataToSend(0))
1229
+ .WillProduceOnce(createDataToSend(1))
1230
+ .WillProduceOnce(createDataToSend(2))
1231
+ .WillProduceOnce(createDataToSend(3))
1232
+ .WillProduceOnce(createDataToSend(4))
1233
+ .WillProduceOnce(createDataToSend(5))
1234
+ .WillProduceOnce(createDataToSend(6))
1235
+ .WillProduceOnce(createDataToSend(7))
1236
+ .WillProduceRepeatedly(
1237
+ [](uint64_t, size_t)
1238
+ {
1239
+ return std::nullopt;
1240
+ });
1241
+
1242
+ REQUIRE(
1243
+ getSentPacketTSNs(retransmissionQueue) ==
1244
+ std::vector<uint32_t>{ 10, 11, 12, 13, 14, 15, 16, 17 });
1245
+
1246
+ REQUIRE(
1247
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(8, Arwnd).get()) == false);
1248
+ REQUIRE(
1249
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(9, Arwnd).get()) == true);
1250
+ REQUIRE(
1251
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(10, Arwnd).get()) == true);
1252
+ REQUIRE(
1253
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(11, Arwnd).get()) == true);
1254
+ REQUIRE(
1255
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(12, Arwnd).get()) == true);
1256
+ REQUIRE(
1257
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(13, Arwnd).get()) == true);
1258
+ REQUIRE(
1259
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(14, Arwnd).get()) == true);
1260
+ REQUIRE(
1261
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(15, Arwnd).get()) == true);
1262
+ REQUIRE(
1263
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(16, Arwnd).get()) == true);
1264
+ REQUIRE(
1265
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(17, Arwnd).get()) == true);
1266
+ // TSN 18 has never been sent -> rejected.
1267
+ REQUIRE(
1268
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(18, Arwnd).get()) == false);
1269
+ }
1270
+
1271
+ SECTION("handle gap-ack-blocks matching no inflight data")
1272
+ {
1273
+ auto retransmissionQueue = createRetransmissionQueue();
1274
+
1275
+ sendQueue.WillProduceOnce(createDataToSend(0))
1276
+ .WillProduceOnce(createDataToSend(1))
1277
+ .WillProduceOnce(createDataToSend(2))
1278
+ .WillProduceOnce(createDataToSend(3))
1279
+ .WillProduceOnce(createDataToSend(4))
1280
+ .WillProduceOnce(createDataToSend(5))
1281
+ .WillProduceOnce(createDataToSend(6))
1282
+ .WillProduceOnce(createDataToSend(7))
1283
+ .WillProduceRepeatedly(
1284
+ [](uint64_t, size_t)
1285
+ {
1286
+ return std::nullopt;
1287
+ });
1288
+
1289
+ REQUIRE(
1290
+ getSentPacketTSNs(retransmissionQueue) ==
1291
+ std::vector<uint32_t>{ 10, 11, 12, 13, 14, 15, 16, 17 });
1292
+
1293
+ // Ack 9, 20-25. This is an invalid SACK Chunk, but should still be handled.
1294
+ retransmissionQueue.HandleReceivedSackChunk(
1295
+ nowMs,
1296
+ createSackChunk(
1297
+ 9,
1298
+ Arwnd,
1299
+ {
1300
+ { 11, 16 },
1301
+ })
1302
+ .get());
1303
+
1304
+ REQUIRE(
1305
+ retransmissionQueue.GetChunkStatesForTesting() ==
1306
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
1307
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
1308
+ { 10, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1309
+ { 11, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1310
+ { 12, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1311
+ { 13, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1312
+ { 14, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1313
+ { 15, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1314
+ { 16, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1315
+ { 17, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1316
+ });
1317
+ }
1318
+
1319
+ SECTION("handle invalid gap-ack-blocks")
1320
+ {
1321
+ // Nothing outstanding. Gap blocks referencing non-existent TSNs are
1322
+ // rejected.
1323
+
1324
+ auto retransmissionQueue = createRetransmissionQueue();
1325
+
1326
+ // cumTsn=9 (no change), gap {3,4} -> TSN 12-13, both beyond
1327
+ // highestOutstandingTsn(9) -> rejected. State unchanged.
1328
+ retransmissionQueue.HandleReceivedSackChunk(
1329
+ nowMs,
1330
+ createSackChunk(
1331
+ 9,
1332
+ Arwnd,
1333
+ {
1334
+ { 3, 4 },
1335
+ })
1336
+ .get());
1337
+
1338
+ REQUIRE(
1339
+ retransmissionQueue.GetChunkStatesForTesting() ==
1340
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
1341
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
1342
+ });
1343
+ }
1344
+
1345
+ SECTION("gap-ack-blocks do not move cumulative TSN ack")
1346
+ {
1347
+ // cumTsn=9, gap {1,5} acks TSN 10-14 via gap blocks. The cumulative TSN
1348
+ // ack point itself must NOT advance, gap acks are renegable.
1349
+
1350
+ auto retransmissionQueue = createRetransmissionQueue();
1351
+
1352
+ sendQueue.WillProduceOnce(createDataToSend(0))
1353
+ .WillProduceOnce(createDataToSend(1))
1354
+ .WillProduceOnce(createDataToSend(2))
1355
+ .WillProduceOnce(createDataToSend(3))
1356
+ .WillProduceOnce(createDataToSend(4))
1357
+ .WillProduceOnce(createDataToSend(5))
1358
+ .WillProduceOnce(createDataToSend(6))
1359
+ .WillProduceOnce(createDataToSend(7))
1360
+ .WillProduceRepeatedly(
1361
+ [](uint64_t, size_t)
1362
+ {
1363
+ return std::nullopt;
1364
+ });
1365
+
1366
+ REQUIRE(
1367
+ getSentPacketTSNs(retransmissionQueue) ==
1368
+ std::vector<uint32_t>{ 10, 11, 12, 13, 14, 15, 16, 17 });
1369
+
1370
+ // Ack 9, 10-14. This is actually an invalid ACK as the first gap can't be
1371
+ // adjacent to the cum-tsn-ack, but it's not strictly forbidden. However,
1372
+ // the cum-tsn-ack should not move, as the gap-ack-blocks are just advisory.
1373
+ retransmissionQueue.HandleReceivedSackChunk(
1374
+ nowMs,
1375
+ createSackChunk(
1376
+ 9,
1377
+ Arwnd,
1378
+ {
1379
+ { 1, 5 },
1380
+ })
1381
+ .get());
1382
+
1383
+ REQUIRE(
1384
+ retransmissionQueue.GetChunkStatesForTesting() ==
1385
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
1386
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
1387
+ { 10, RTC::SCTP::OutstandingData::State::ACKED },
1388
+ { 11, RTC::SCTP::OutstandingData::State::ACKED },
1389
+ { 12, RTC::SCTP::OutstandingData::State::ACKED },
1390
+ { 13, RTC::SCTP::OutstandingData::State::ACKED },
1391
+ { 14, RTC::SCTP::OutstandingData::State::ACKED },
1392
+ { 15, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1393
+ { 16, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1394
+ { 17, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1395
+ });
1396
+ }
1397
+
1398
+ SECTION("stays within available size")
1399
+ {
1400
+ // With `GetChunksToSend(nowMs, 1188-12=1176)`, the first `Produce()` receives
1401
+ // 1176 - DataChunkHeaderLength bytes, the second receives the remainder.
1402
+
1403
+ auto retransmissionQueue = createRetransmissionQueue();
1404
+ constexpr size_t AvailableBytes{ 1188 - 12 }; // 1176
1405
+
1406
+ bool sizeCheck1Ok{ false };
1407
+ bool sizeCheck2Ok{ false };
1408
+
1409
+ sendQueue
1410
+ .WillProduceOnce(
1411
+ [&sizeCheck1Ok](uint64_t /*nowMs*/, size_t maxLength)
1412
+ {
1413
+ sizeCheck1Ok = (maxLength == AvailableBytes - RTC::SCTP::DataChunk::DataChunkHeaderLength);
1414
+
1415
+ std::vector<uint8_t> payload(183, 0x00);
1416
+
1417
+ return RTC::SCTP::SendQueueInterface::DataToSend(
1418
+ 0, RTC::SCTP::UserData(1, 0, 0, 0, 53, std::move(payload), true, true, false));
1419
+ })
1420
+ .WillProduceOnce(
1421
+ [&sizeCheck2Ok](uint64_t /*nowMs*/, size_t maxLength)
1422
+ {
1423
+ sizeCheck2Ok = (maxLength == 976 - RTC::SCTP::DataChunk::DataChunkHeaderLength);
1424
+
1425
+ std::vector<uint8_t> payload(957, 0x00);
1426
+
1427
+ return RTC::SCTP::SendQueueInterface::DataToSend(
1428
+ 1, RTC::SCTP::UserData(1, 0, 0, 0, 53, std::move(payload), true, true, false));
1429
+ });
1430
+
1431
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, AvailableBytes) == std::vector<uint32_t>{ 10, 11 });
1432
+ REQUIRE(sizeCheck1Ok == true);
1433
+ REQUIRE(sizeCheck2Ok == true);
1434
+ }
1435
+
1436
+ SECTION("accounts nacked abandoned chunks as not outstanding")
1437
+ {
1438
+ auto retransmissionQueue = createRetransmissionQueue();
1439
+
1440
+ const size_t chunkSerializedLength = RTC::SCTP::DataChunk::DataChunkHeaderLength + 4;
1441
+
1442
+ REQUIRE(chunkSerializedLength == 16 + 4);
1443
+
1444
+ // Three middle fragments of the same message, maxRetransmissions=0.
1445
+ sendQueue
1446
+ .WillProduceOnce(
1447
+ [](uint64_t /*nowMs*/, size_t /*maxLength*/)
1448
+ {
1449
+ RTC::SCTP::UserData data(1, 0, 0, 0, 53, { 0x01, 0x02, 0x03, 0x04 }, true, false, false);
1450
+ RTC::SCTP::SendQueueInterface::DataToSend dataToSend(42, std::move(data));
1451
+
1452
+ dataToSend.maxRetransmissions = 0;
1453
+
1454
+ return dataToSend;
1455
+ })
1456
+ .WillProduceOnce(
1457
+ [](uint64_t /*nowMs*/, size_t /*maxLength*/)
1458
+ {
1459
+ RTC::SCTP::UserData data(1, 0, 0, 0, 53, { 0x05, 0x06, 0x07, 0x08 }, false, false, false);
1460
+ RTC::SCTP::SendQueueInterface::DataToSend dataToSend(42, std::move(data));
1461
+
1462
+ dataToSend.maxRetransmissions = 0;
1463
+
1464
+ return dataToSend;
1465
+ })
1466
+ .WillProduceOnce(
1467
+ [](uint64_t /*nowMs*/, size_t /*maxLength*/)
1468
+ {
1469
+ RTC::SCTP::UserData data(1, 0, 0, 0, 53, { 0x09, 0x0a, 0x0b, 0x0c }, false, false, false);
1470
+ RTC::SCTP::SendQueueInterface::DataToSend dataToSend(42, std::move(data));
1471
+
1472
+ dataToSend.maxRetransmissions = 0;
1473
+
1474
+ return dataToSend;
1475
+ })
1476
+ .WillProduceRepeatedly(
1477
+ [](uint64_t, size_t)
1478
+ {
1479
+ return std::nullopt;
1480
+ });
1481
+
1482
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, 1000) == std::vector<uint32_t>{ 10, 11, 12 });
1483
+ REQUIRE(
1484
+ retransmissionQueue.GetChunkStatesForTesting() ==
1485
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
1486
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
1487
+ { 10, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1488
+ { 11, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1489
+ { 12, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1490
+ });
1491
+ REQUIRE(retransmissionQueue.GetUnackedPacketBytes() == chunkSerializedLength * 3);
1492
+ REQUIRE(retransmissionQueue.GetUnackedItems() == 3);
1493
+
1494
+ // Mark the message as lost.
1495
+ sendQueue.WillDiscardOnce(1, 42, /*returnValue*/ false);
1496
+
1497
+ retransmissionQueue.HandleT3RtxTimerExpiry();
1498
+
1499
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == true);
1500
+
1501
+ REQUIRE(
1502
+ retransmissionQueue.GetChunkStatesForTesting() ==
1503
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
1504
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
1505
+ { 10, RTC::SCTP::OutstandingData::State::ABANDONED },
1506
+ { 11, RTC::SCTP::OutstandingData::State::ABANDONED },
1507
+ { 12, RTC::SCTP::OutstandingData::State::ABANDONED },
1508
+ });
1509
+ // Abandoned chunks are not counted as outstanding.
1510
+ REQUIRE(retransmissionQueue.GetUnackedPacketBytes() == 0);
1511
+ REQUIRE(retransmissionQueue.GetUnackedItems() == 0);
1512
+
1513
+ // Acking abandoned chunks one by one changes nothing in the counters.
1514
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(10, Arwnd).get());
1515
+
1516
+ REQUIRE(retransmissionQueue.GetUnackedPacketBytes() == 0);
1517
+ REQUIRE(retransmissionQueue.GetUnackedItems() == 0);
1518
+
1519
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(11, Arwnd).get());
1520
+
1521
+ REQUIRE(retransmissionQueue.GetUnackedPacketBytes() == 0);
1522
+ REQUIRE(retransmissionQueue.GetUnackedItems() == 0);
1523
+
1524
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(12, Arwnd).get());
1525
+
1526
+ REQUIRE(retransmissionQueue.GetUnackedPacketBytes() == 0);
1527
+ REQUIRE(retransmissionQueue.GetUnackedItems() == 0);
1528
+ }
1529
+
1530
+ SECTION("expire from send queue when partially sent")
1531
+ {
1532
+ // Two fragments on stream 17, outgoingMessageId=42. First is produced and
1533
+ // goes in flight. After nowMs advances past `expiresAtMs`, the second is
1534
+ // produced but expired on Insert() -> first also abandoned, `Discard()`
1535
+ // called (returns true -> placeholder TSN 12).
1536
+
1537
+ auto retransmissionQueue = createRetransmissionQueue();
1538
+
1539
+ const uint64_t expiresAtMs = nowMs + 10;
1540
+
1541
+ sendQueue
1542
+ .WillProduceOnce(
1543
+ [expiresAtMs](uint64_t /*nowMs*/, size_t /*maxLength*/)
1544
+ {
1545
+ RTC::SCTP::UserData data(17, 0, 0, 0, 53, { 0x01, 0x02, 0x03, 0x04 }, true, false, false);
1546
+ RTC::SCTP::SendQueueInterface::DataToSend dataToSend(42, std::move(data));
1547
+
1548
+ dataToSend.expiresAtMs = expiresAtMs;
1549
+
1550
+ return dataToSend;
1551
+ })
1552
+ .WillProduceOnce(
1553
+ [expiresAtMs](uint64_t /*nowMs*/, size_t /*maxLength*/)
1554
+ {
1555
+ RTC::SCTP::UserData data(17, 0, 0, 0, 53, { 0x05, 0x06, 0x07, 0x08 }, false, false, false);
1556
+ RTC::SCTP::SendQueueInterface::DataToSend dataToSend(42, std::move(data));
1557
+
1558
+ dataToSend.expiresAtMs = expiresAtMs;
1559
+
1560
+ return dataToSend;
1561
+ })
1562
+ .WillProduceRepeatedly(
1563
+ [](uint64_t, size_t)
1564
+ {
1565
+ return std::nullopt;
1566
+ });
1567
+
1568
+ // First `GetChunksToSend()` produces TSN 10 (nowMs < expiresAtMs).
1569
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, 24) == std::vector<uint32_t>{ 10 });
1570
+
1571
+ // Advance past expiry.
1572
+ nowMs += 100;
1573
+
1574
+ // `Discard()` called for TSN 11 (unsent tail) -> returns true -> placeholder
1575
+ // TSN 12.
1576
+ sendQueue.WillDiscardOnce(17, 42, /*returnValue*/ true);
1577
+
1578
+ // Second `GetChunksToSend()` produces TSN 11 but now > expiresAtMs ->
1579
+ // abandoned on `Insert()`, TSN 10 also abandoned, placeholder TSN 12
1580
+ // created.
1581
+ REQUIRE(retransmissionQueue.GetChunksToSend(nowMs, 24).empty());
1582
+
1583
+ REQUIRE(
1584
+ retransmissionQueue.GetChunkStatesForTesting() ==
1585
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
1586
+ { 9, RTC::SCTP::OutstandingData::State::ACKED }, // Initial TSN.
1587
+ { 10, RTC::SCTP::OutstandingData::State::ABANDONED }, // Produced and in-flight.
1588
+ { 11, RTC::SCTP::OutstandingData::State::ABANDONED }, // Produced and expired.
1589
+ { 12, RTC::SCTP::OutstandingData::State::ABANDONED }, // Placeholder end.
1590
+ });
1591
+ }
1592
+
1593
+ SECTION("expire correct message from send queue")
1594
+ {
1595
+ // Three messages on stream 1. Messages 42 (mid=0) and 43 (mid=1) are
1596
+ // complete single-fragment messages. Message 44 (mid=0, stream reset)
1597
+ // has a beginning fragment produced before expiry and a middle fragment
1598
+ // produced after expiry -> message 44 gets abandoned, messages 42 and 43
1599
+ // remain IN_FLIGHT.
1600
+
1601
+ auto retransmissionQueue = createRetransmissionQueue();
1602
+
1603
+ const uint64_t expiresAtMs = nowMs + 10;
1604
+
1605
+ // outgoingMessageId=42, mid=0, "BE" — complete message.
1606
+ sendQueue
1607
+ .WillProduceOnce(
1608
+ [expiresAtMs](uint64_t /*nowMs*/, size_t /*maxLength*/)
1609
+ {
1610
+ RTC::SCTP::UserData data(1, 0, 0, 0, 53, { 0x01, 0x02, 0x03, 0x04 }, true, true, false);
1611
+ RTC::SCTP::SendQueueInterface::DataToSend dataToSend(42, std::move(data));
1612
+
1613
+ dataToSend.expiresAtMs = expiresAtMs;
1614
+
1615
+ return dataToSend;
1616
+ })
1617
+ // outgoingMessageId=43, mid=1, "BE" — complete message.
1618
+ .WillProduceOnce(
1619
+ [expiresAtMs](uint64_t /*nowMs*/, size_t /*maxLength*/)
1620
+ {
1621
+ RTC::SCTP::UserData data(1, 0, 1, 0, 53, { 0x01, 0x02, 0x03, 0x04 }, true, true, false);
1622
+ RTC::SCTP::SendQueueInterface::DataToSend dataToSend(43, std::move(data));
1623
+
1624
+ dataToSend.expiresAtMs = expiresAtMs;
1625
+
1626
+ return dataToSend;
1627
+ })
1628
+ // outgoingMessageId=44, mid=0 (stream reset), "B" — beginning only.
1629
+ .WillProduceOnce(
1630
+ [expiresAtMs](uint64_t /*nowMs*/, size_t /*maxLength*/)
1631
+ {
1632
+ RTC::SCTP::UserData data(1, 0, 0, 0, 53, { 0x01, 0x02, 0x03, 0x04 }, true, false, false);
1633
+ RTC::SCTP::SendQueueInterface::DataToSend dataToSend(44, std::move(data));
1634
+
1635
+ dataToSend.expiresAtMs = expiresAtMs;
1636
+
1637
+ return dataToSend;
1638
+ })
1639
+ // outgoingMessageId=44, mid=0, middle fragment (produced after expiry).
1640
+ .WillProduceOnce(
1641
+ [expiresAtMs](uint64_t /*nowMs*/, size_t /*maxLength*/)
1642
+ {
1643
+ RTC::SCTP::UserData data(1, 0, 0, 0, 53, { 0x05, 0x06, 0x07, 0x08 }, false, false, false);
1644
+ RTC::SCTP::SendQueueInterface::DataToSend dataToSend(44, std::move(data));
1645
+
1646
+ dataToSend.expiresAtMs = expiresAtMs;
1647
+
1648
+ return dataToSend;
1649
+ })
1650
+ .WillProduceRepeatedly(
1651
+ [](uint64_t, size_t)
1652
+ {
1653
+ return std::nullopt;
1654
+ });
1655
+
1656
+ std::vector<std::pair<uint32_t, RTC::SCTP::UserData>> expectedChunksToSend;
1657
+
1658
+ // TSN 10, msgId=42.
1659
+ expectedChunksToSend.emplace_back(
1660
+ 10,
1661
+ RTC::SCTP::UserData{
1662
+ 1, 0, 0, 0, 53, { 0x01, 0x02, 0x03, 0x04 },
1663
+ true, true, false
1664
+ });
1665
+
1666
+ REQUIRE(retransmissionQueue.GetChunksToSend(nowMs, 24) == expectedChunksToSend);
1667
+
1668
+ // TSN 11, msgId=43.
1669
+ expectedChunksToSend.clear();
1670
+ expectedChunksToSend.emplace_back(
1671
+ 11,
1672
+ RTC::SCTP::UserData{
1673
+ 1, 0, 1, 0, 53, { 0x01, 0x02, 0x03, 0x04 },
1674
+ true, true, false
1675
+ });
1676
+
1677
+ REQUIRE(retransmissionQueue.GetChunksToSend(nowMs, 24) == expectedChunksToSend);
1678
+
1679
+ // TSN 12, msgId=44 "B"
1680
+ expectedChunksToSend.clear();
1681
+ expectedChunksToSend.emplace_back(
1682
+ 12,
1683
+ RTC::SCTP::UserData{
1684
+ 1, 0, 0, 0, 53, { 0x01, 0x02, 0x03, 0x04 },
1685
+ true, false, false
1686
+ });
1687
+
1688
+ REQUIRE(retransmissionQueue.GetChunksToSend(nowMs, 24) == expectedChunksToSend);
1689
+
1690
+ // Advance past expiry.
1691
+ nowMs += 100;
1692
+
1693
+ // `Discard()` called for message 44 (unsent middle fragment), returns true
1694
+ // -> placeholder TSN 14 created.
1695
+ sendQueue.WillDiscardOnce(1, 44, /*returnValue*/ true);
1696
+
1697
+ // Fourth call produces TSN 13 (middle of message 44) but it's now expired
1698
+ // -> TSN 12 and 13 abandoned, placeholder TSN 14 created.
1699
+ REQUIRE(retransmissionQueue.GetChunksToSend(nowMs, 24).empty());
1700
+
1701
+ REQUIRE(
1702
+ retransmissionQueue.GetChunkStatesForTesting() ==
1703
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
1704
+ { 9, RTC::SCTP::OutstandingData::State::ACKED }, // Initial TSN.
1705
+ { 10, RTC::SCTP::OutstandingData::State::IN_FLIGHT }, // msgId=42, BE.
1706
+ { 11, RTC::SCTP::OutstandingData::State::IN_FLIGHT }, // msgId=43, BE.
1707
+ { 12, RTC::SCTP::OutstandingData::State::ABANDONED }, // msgId=44, B.
1708
+ { 13, RTC::SCTP::OutstandingData::State::ABANDONED }, // msgId=44, produced and expired.
1709
+ { 14, RTC::SCTP::OutstandingData::State::ABANDONED }, // Placeholder end.
1710
+ });
1711
+ }
1712
+
1713
+ SECTION("limits retransmissions only when nacked three times")
1714
+ {
1715
+ // A chunk with maxRetransmissions=0 is NOT abandoned immediately when
1716
+ // nacked — it takes exactly three nacks like any other chunk, and is
1717
+ // abandoned on the third (not retransmitted, since maxRetransmissions=0).
1718
+
1719
+ auto retransmissionQueue = createRetransmissionQueue();
1720
+
1721
+ // TSN 10: maxRetransmissions=0.
1722
+ sendQueue.WillProduceOnce(createDataToSend(42, /*maxRetransmissions*/ 0))
1723
+ .WillProduceOnce(createDataToSend(0)) // TSN 11.
1724
+ .WillProduceOnce(createDataToSend(1)) // TSN 12.
1725
+ .WillProduceOnce(createDataToSend(2)) // TSN 13.
1726
+ .WillProduceRepeatedly(
1727
+ [](uint64_t, size_t)
1728
+ {
1729
+ return std::nullopt;
1730
+ });
1731
+
1732
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == false);
1733
+
1734
+ REQUIRE(getSentPacketTSNs(retransmissionQueue) == std::vector<uint32_t>{ 10, 11, 12, 13 });
1735
+ REQUIRE(
1736
+ retransmissionQueue.GetChunkStatesForTesting() ==
1737
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
1738
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
1739
+ { 10, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1740
+ { 11, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1741
+ { 12, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1742
+ { 13, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1743
+ });
1744
+
1745
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == false);
1746
+
1747
+ // `Discard()` must NOT be called for the first two nacks.
1748
+ sendQueue.ExpectDiscardCalledTimes(0);
1749
+
1750
+ // First nack for TSN 10.
1751
+ retransmissionQueue.HandleReceivedSackChunk(
1752
+ nowMs,
1753
+ createSackChunk(
1754
+ 9,
1755
+ Arwnd,
1756
+ {
1757
+ { 2, 2 },
1758
+ })
1759
+ .get());
1760
+
1761
+ REQUIRE(
1762
+ retransmissionQueue.GetChunkStatesForTesting() ==
1763
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
1764
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
1765
+ { 10, RTC::SCTP::OutstandingData::State::NACKED },
1766
+ { 11, RTC::SCTP::OutstandingData::State::ACKED },
1767
+ { 12, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1768
+ { 13, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1769
+ });
1770
+
1771
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == false);
1772
+
1773
+ // Second nack for TSN 10.
1774
+ retransmissionQueue.HandleReceivedSackChunk(
1775
+ nowMs,
1776
+ createSackChunk(
1777
+ 9,
1778
+ Arwnd,
1779
+ {
1780
+ { 2, 3 },
1781
+ })
1782
+ .get());
1783
+
1784
+ REQUIRE(
1785
+ retransmissionQueue.GetChunkStatesForTesting() ==
1786
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
1787
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
1788
+ { 10, RTC::SCTP::OutstandingData::State::NACKED },
1789
+ { 11, RTC::SCTP::OutstandingData::State::ACKED },
1790
+ { 12, RTC::SCTP::OutstandingData::State::ACKED },
1791
+ { 13, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1792
+ });
1793
+
1794
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == false);
1795
+
1796
+ REQUIRE_VERIFICATION_RESULT(sendQueue.VerifyExpectations());
1797
+
1798
+ // Third nack -> TSN 10 abandoned (maxRetransmissions=0 means 0
1799
+ // retransmits).
1800
+ sendQueue.WillDiscardOnce(1, 42, /*returnValue*/ false);
1801
+
1802
+ retransmissionQueue.HandleReceivedSackChunk(
1803
+ nowMs,
1804
+ createSackChunk(
1805
+ 9,
1806
+ Arwnd,
1807
+ {
1808
+ { 2, 4 },
1809
+ })
1810
+ .get());
1811
+
1812
+ REQUIRE(
1813
+ retransmissionQueue.GetChunkStatesForTesting() ==
1814
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
1815
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
1816
+ { 10, RTC::SCTP::OutstandingData::State::ABANDONED },
1817
+ { 11, RTC::SCTP::OutstandingData::State::ACKED },
1818
+ { 12, RTC::SCTP::OutstandingData::State::ACKED },
1819
+ { 13, RTC::SCTP::OutstandingData::State::ACKED },
1820
+ });
1821
+
1822
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == true);
1823
+ }
1824
+
1825
+ SECTION("abandons rtx limit 2 when nacked nine times")
1826
+ {
1827
+ // maxRetransmits=2 for TSN 10: first 3 nacks -> fast-retransmit #1;
1828
+ // next 3 nacks -> regular retransmit #2; next 3 nacks -> abandoned.
1829
+
1830
+ auto retransmissionQueue = createRetransmissionQueue();
1831
+
1832
+ // TSN 10: maxRetransmissions=2.
1833
+ sendQueue.WillProduceOnce(createDataToSend(42, /*maxRetransmissions*/ 2))
1834
+ .WillProduceOnce(createDataToSend(0)) // TSN 11.
1835
+ .WillProduceOnce(createDataToSend(1)) // TSN 12.
1836
+ .WillProduceOnce(createDataToSend(2)) // TSN 13.
1837
+ .WillProduceOnce(createDataToSend(3)) // TSN 14.
1838
+ .WillProduceOnce(createDataToSend(4)) // TSN 15.
1839
+ .WillProduceOnce(createDataToSend(5)) // TSN 16.
1840
+ .WillProduceOnce(createDataToSend(6)) // TSN 17.
1841
+ .WillProduceOnce(createDataToSend(7)) // TSN 18.
1842
+ .WillProduceOnce(createDataToSend(8)) // TSN 19.
1843
+ .WillProduceRepeatedly(
1844
+ [](uint64_t, size_t)
1845
+ {
1846
+ return std::nullopt;
1847
+ });
1848
+
1849
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == false);
1850
+
1851
+ REQUIRE(
1852
+ getSentPacketTSNs(retransmissionQueue) ==
1853
+ std::vector<uint32_t>{ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 });
1854
+ REQUIRE(
1855
+ retransmissionQueue.GetChunkStatesForTesting() ==
1856
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
1857
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
1858
+ { 10, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1859
+ { 11, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1860
+ { 12, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1861
+ { 13, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1862
+ { 14, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1863
+ { 15, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1864
+ { 16, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1865
+ { 17, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1866
+ { 18, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1867
+ { 19, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1868
+ });
1869
+
1870
+ // No `Discard()` calls during nack rounds 1 and 2.
1871
+ sendQueue.ExpectDiscardCalledTimes(0);
1872
+
1873
+ // Ack TSN 11-13 — three nacks for TSN 10 -> TO_BE_RETRANSMITTED.
1874
+ for (uint32_t tsn{ 11 }; tsn <= 13; ++tsn)
1875
+ {
1876
+ retransmissionQueue.HandleReceivedSackChunk(
1877
+ nowMs,
1878
+ createSackChunk(
1879
+ 9,
1880
+ Arwnd,
1881
+ {
1882
+ { 2, static_cast<uint16_t>(tsn - 9) }
1883
+ })
1884
+ .get());
1885
+ }
1886
+
1887
+ REQUIRE(
1888
+ retransmissionQueue.GetChunkStatesForTesting() ==
1889
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
1890
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
1891
+ { 10, RTC::SCTP::OutstandingData::State::TO_BE_RETRANSMITTED },
1892
+ { 11, RTC::SCTP::OutstandingData::State::ACKED },
1893
+ { 12, RTC::SCTP::OutstandingData::State::ACKED },
1894
+ { 13, RTC::SCTP::OutstandingData::State::ACKED },
1895
+ { 14, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1896
+ { 15, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1897
+ { 16, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1898
+ { 17, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1899
+ { 18, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1900
+ { 19, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1901
+ });
1902
+
1903
+ // Fast retransmit #1.
1904
+ REQUIRE(getTSNsForFastRetransmit(retransmissionQueue) == std::vector<uint32_t>{ 10 });
1905
+
1906
+ // Ack TSN 14-16 — three more nacks -> retransmit #2 (TO_BE_RETRANSMITTED).
1907
+ for (uint32_t tsn{ 14 }; tsn <= 16; ++tsn)
1908
+ {
1909
+ retransmissionQueue.HandleReceivedSackChunk(
1910
+ nowMs,
1911
+ createSackChunk(
1912
+ 9,
1913
+ Arwnd,
1914
+ {
1915
+ { 2, static_cast<uint16_t>(tsn - 9) }
1916
+ })
1917
+ .get());
1918
+ }
1919
+
1920
+ REQUIRE(
1921
+ retransmissionQueue.GetChunkStatesForTesting() ==
1922
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
1923
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
1924
+ { 10, RTC::SCTP::OutstandingData::State::TO_BE_RETRANSMITTED },
1925
+ { 11, RTC::SCTP::OutstandingData::State::ACKED },
1926
+ { 12, RTC::SCTP::OutstandingData::State::ACKED },
1927
+ { 13, RTC::SCTP::OutstandingData::State::ACKED },
1928
+ { 14, RTC::SCTP::OutstandingData::State::ACKED },
1929
+ { 15, RTC::SCTP::OutstandingData::State::ACKED },
1930
+ { 16, RTC::SCTP::OutstandingData::State::ACKED },
1931
+ { 17, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1932
+ { 18, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1933
+ { 19, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1934
+ });
1935
+
1936
+ // Regular retransmit #2.
1937
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, 1000) == std::vector<uint32_t>{ 10 });
1938
+
1939
+ // Ack TSN 17-18 — two more nacks (TSN 10 is now in-flight again after retransmit).
1940
+ for (uint32_t tsn{ 17 }; tsn <= 18; ++tsn)
1941
+ {
1942
+ retransmissionQueue.HandleReceivedSackChunk(
1943
+ nowMs,
1944
+ createSackChunk(
1945
+ 9,
1946
+ Arwnd,
1947
+ {
1948
+ { 2, static_cast<uint16_t>(tsn - 9) }
1949
+ })
1950
+ .get());
1951
+ }
1952
+
1953
+ REQUIRE(
1954
+ retransmissionQueue.GetChunkStatesForTesting() ==
1955
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
1956
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
1957
+ { 10, RTC::SCTP::OutstandingData::State::NACKED },
1958
+ { 11, RTC::SCTP::OutstandingData::State::ACKED },
1959
+ { 12, RTC::SCTP::OutstandingData::State::ACKED },
1960
+ { 13, RTC::SCTP::OutstandingData::State::ACKED },
1961
+ { 14, RTC::SCTP::OutstandingData::State::ACKED },
1962
+ { 15, RTC::SCTP::OutstandingData::State::ACKED },
1963
+ { 16, RTC::SCTP::OutstandingData::State::ACKED },
1964
+ { 17, RTC::SCTP::OutstandingData::State::ACKED },
1965
+ { 18, RTC::SCTP::OutstandingData::State::ACKED },
1966
+ { 19, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
1967
+ });
1968
+
1969
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == false);
1970
+
1971
+ REQUIRE_VERIFICATION_RESULT(sendQueue.VerifyExpectations());
1972
+
1973
+ // Ack TSN 19 — third nack; numRetransmissions(2) == maxRetransmissions(2)
1974
+ // -> ABANDON.
1975
+ sendQueue.WillDiscardOnce(1, 42, /*returnValue*/ false);
1976
+
1977
+ retransmissionQueue.HandleReceivedSackChunk(
1978
+ nowMs,
1979
+ createSackChunk(
1980
+ 9,
1981
+ Arwnd,
1982
+ {
1983
+ { 2, 10 }
1984
+ })
1985
+ .get());
1986
+
1987
+ REQUIRE(retransmissionQueue.GetChunksToSend(nowMs, 1000).empty());
1988
+
1989
+ REQUIRE(
1990
+ retransmissionQueue.GetChunkStatesForTesting() ==
1991
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
1992
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
1993
+ { 10, RTC::SCTP::OutstandingData::State::ABANDONED },
1994
+ { 11, RTC::SCTP::OutstandingData::State::ACKED },
1995
+ { 12, RTC::SCTP::OutstandingData::State::ACKED },
1996
+ { 13, RTC::SCTP::OutstandingData::State::ACKED },
1997
+ { 14, RTC::SCTP::OutstandingData::State::ACKED },
1998
+ { 15, RTC::SCTP::OutstandingData::State::ACKED },
1999
+ { 16, RTC::SCTP::OutstandingData::State::ACKED },
2000
+ { 17, RTC::SCTP::OutstandingData::State::ACKED },
2001
+ { 18, RTC::SCTP::OutstandingData::State::ACKED },
2002
+ { 19, RTC::SCTP::OutstandingData::State::ACKED },
2003
+ });
2004
+
2005
+ REQUIRE(retransmissionQueue.ShouldSendForwardTsn(nowMs) == true);
2006
+ }
2007
+
2008
+ SECTION("cwnd recovers when acking")
2009
+ {
2010
+ auto retransmissionQueue = createRetransmissionQueue();
2011
+
2012
+ constexpr size_t Cwnd{ 1200 };
2013
+
2014
+ retransmissionQueue.SetCwnd(Cwnd);
2015
+
2016
+ REQUIRE(retransmissionQueue.GetCwnd() == Cwnd);
2017
+
2018
+ const std::vector<uint8_t> payload(1000, 0x00);
2019
+ const size_t chunkSerializedLength = RTC::SCTP::DataChunk::DataChunkHeaderLength + payload.size();
2020
+
2021
+ sendQueue
2022
+ .WillProduceOnce(
2023
+ [&payload](uint64_t /*nowMs*/, size_t /*maxLength*/)
2024
+ {
2025
+ return RTC::SCTP::SendQueueInterface::DataToSend(
2026
+ 0, RTC::SCTP::UserData(1, 0, 0, 0, 53, payload, true, true, false));
2027
+ })
2028
+ .WillProduceRepeatedly(
2029
+ [](uint64_t, size_t)
2030
+ {
2031
+ return std::nullopt;
2032
+ });
2033
+
2034
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, 1500) == std::vector<uint32_t>{ 10 });
2035
+ REQUIRE(retransmissionQueue.GetUnackedPacketBytes() == chunkSerializedLength);
2036
+
2037
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(10, Arwnd).get());
2038
+
2039
+ REQUIRE(retransmissionQueue.GetCwnd() == Cwnd + chunkSerializedLength);
2040
+ }
2041
+
2042
+ SECTION("can always send one packet")
2043
+ {
2044
+ auto retransmissionQueue = createRetransmissionQueue();
2045
+
2046
+ const size_t mtu{ Utils::Byte::PadDownTo4Bytes(Mtu) }; // 1188.
2047
+ const std::vector<uint8_t> payload(mtu - 100, 0x00); // 1088 bytes.
2048
+
2049
+ sendQueue
2050
+ .WillProduceOnce(
2051
+ [&payload](uint64_t, size_t)
2052
+ {
2053
+ return RTC::SCTP::SendQueueInterface::DataToSend(
2054
+ 0, RTC::SCTP::UserData(1, 0, 0, 0, 53, payload, true, false, false));
2055
+ })
2056
+ .WillProduceOnce(
2057
+ [&payload](uint64_t, size_t)
2058
+ {
2059
+ return RTC::SCTP::SendQueueInterface::DataToSend(
2060
+ 0, RTC::SCTP::UserData(1, 0, 0, 0, 53, payload, false, false, false));
2061
+ })
2062
+ .WillProduceOnce(
2063
+ [&payload](uint64_t, size_t)
2064
+ {
2065
+ return RTC::SCTP::SendQueueInterface::DataToSend(
2066
+ 0, RTC::SCTP::UserData(1, 0, 0, 0, 53, payload, false, false, false));
2067
+ })
2068
+ .WillProduceOnce(
2069
+ [&payload](uint64_t, size_t)
2070
+ {
2071
+ return RTC::SCTP::SendQueueInterface::DataToSend(
2072
+ 0, RTC::SCTP::UserData(1, 0, 0, 0, 53, payload, false, false, false));
2073
+ })
2074
+ .WillProduceOnce(
2075
+ [&payload](uint64_t, size_t)
2076
+ {
2077
+ return RTC::SCTP::SendQueueInterface::DataToSend(
2078
+ 0, RTC::SCTP::UserData(1, 0, 0, 0, 53, payload, false, true, false));
2079
+ })
2080
+ .WillProduceRepeatedly(
2081
+ [](uint64_t, size_t)
2082
+ {
2083
+ return std::nullopt;
2084
+ });
2085
+
2086
+ // Produce all 5 chunks (TSN 10-14) in one call.
2087
+ REQUIRE(
2088
+ getSentPacketTSNs(retransmissionQueue, 5 * mtu) == std::vector<uint32_t>{ 10, 11, 12, 13, 14 });
2089
+ REQUIRE(
2090
+ retransmissionQueue.GetChunkStatesForTesting() ==
2091
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
2092
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
2093
+ { 10, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
2094
+ { 11, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
2095
+ { 12, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
2096
+ { 13, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
2097
+ { 14, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
2098
+ });
2099
+
2100
+ // Ack 12, and report an empty receiver window (the peer obviously has a
2101
+ // tiny receive window).
2102
+ retransmissionQueue.HandleReceivedSackChunk(
2103
+ nowMs,
2104
+ createSackChunk(
2105
+ 9,
2106
+ /*aRwnd*/ 0,
2107
+ {
2108
+ { 3, 3 }
2109
+ })
2110
+ .get());
2111
+
2112
+ // Force TSN 10 to be retransmitted.
2113
+ retransmissionQueue.HandleT3RtxTimerExpiry();
2114
+
2115
+ // Even with rwnd=0, one packet can be sent (no in-flight data after NackAll).
2116
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, mtu) == std::vector<uint32_t>{ 10 });
2117
+
2118
+ // But not a second one — TSN 10 is now in-flight again.
2119
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, mtu).empty());
2120
+
2121
+ // Still rwnd=0, TSN 10 in-flight.
2122
+ retransmissionQueue.HandleReceivedSackChunk(
2123
+ nowMs,
2124
+ createSackChunk(
2125
+ 9,
2126
+ /*aRwnd=*/0,
2127
+ {
2128
+ { 3, 3 }
2129
+ })
2130
+ .get());
2131
+
2132
+ // There is in-flight data, so new data should not be allowed to be send since
2133
+ // the receiver window is full.
2134
+ REQUIRE(retransmissionQueue.GetChunksToSend(nowMs, mtu).empty());
2135
+
2136
+ // Ack TSN 10 (no more in-flight data), still rwnd=0.
2137
+ retransmissionQueue.HandleReceivedSackChunk(
2138
+ nowMs,
2139
+ createSackChunk(
2140
+ 10,
2141
+ /*aRwnd=*/0,
2142
+ {
2143
+ { 2, 2 }
2144
+ })
2145
+ .get());
2146
+
2147
+ // TSN 11 can be sent since there is no in-flight data.
2148
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, mtu) == std::vector<uint32_t>{ 11 });
2149
+
2150
+ // But not a second one.
2151
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, mtu).empty());
2152
+
2153
+ // Ack and recover the receiver window
2154
+ retransmissionQueue.HandleReceivedSackChunk(
2155
+ nowMs, createSackChunk(12, static_cast<uint32_t>(5 * mtu)).get());
2156
+
2157
+ // Remaining TO_BE_RETRANSMITTED chunks can now be sent.
2158
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, mtu) == std::vector<uint32_t>{ 13 });
2159
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, mtu) == std::vector<uint32_t>{ 14 });
2160
+ REQUIRE(getSentPacketTSNs(retransmissionQueue, mtu).empty());
2161
+ }
2162
+
2163
+ SECTION("updates rwnd from SACK and unacked payload bytes")
2164
+ {
2165
+ auto retransmissionQueue = createRetransmissionQueue();
2166
+
2167
+ REQUIRE(retransmissionQueue.GetRwnd() == Arwnd);
2168
+
2169
+ // Payload is 4 bytes (padded to 4).
2170
+ constexpr size_t PayloadSize{ 4 };
2171
+
2172
+ sendQueue
2173
+ .WillProduceOnce(createDataToSend(0)) // TSN 10.
2174
+ .WillProduceOnce(createDataToSend(1)) // TSN 11.
2175
+ .WillProduceOnce(createDataToSend(2)) // TSN 12.
2176
+ .WillProduceRepeatedly(
2177
+ [](uint64_t, size_t)
2178
+ {
2179
+ return std::nullopt;
2180
+ });
2181
+
2182
+ REQUIRE(getSentPacketTSNs(retransmissionQueue) == std::vector<uint32_t>{ 10, 11, 12 });
2183
+ REQUIRE(
2184
+ retransmissionQueue.GetChunkStatesForTesting() ==
2185
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
2186
+ { 9, RTC::SCTP::OutstandingData::State::ACKED },
2187
+ { 10, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
2188
+ { 11, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
2189
+ { 12, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
2190
+ });
2191
+
2192
+ REQUIRE(retransmissionQueue.GetRwnd() == Arwnd - (PayloadSize * 3));
2193
+
2194
+ // Ack TSN 10, new aRwnd=1000.
2195
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(10, 1000).get());
2196
+
2197
+ REQUIRE(
2198
+ retransmissionQueue.GetChunkStatesForTesting() ==
2199
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
2200
+ { 10, RTC::SCTP::OutstandingData::State::ACKED },
2201
+ { 11, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
2202
+ { 12, RTC::SCTP::OutstandingData::State::IN_FLIGHT },
2203
+ });
2204
+
2205
+ REQUIRE(retransmissionQueue.GetRwnd() == 1000 - (PayloadSize * 2));
2206
+
2207
+ // Ack everything, new aRwnd=2000.
2208
+ retransmissionQueue.HandleReceivedSackChunk(nowMs, createSackChunk(12, 2000).get());
2209
+
2210
+ REQUIRE(
2211
+ retransmissionQueue.GetChunkStatesForTesting() ==
2212
+ std::vector<std::pair<uint32_t /*tsn*/, RTC::SCTP::OutstandingData::State>>{
2213
+ { 12, RTC::SCTP::OutstandingData::State::ACKED },
2214
+ });
2215
+
2216
+ REQUIRE(retransmissionQueue.GetRwnd() == 2000);
2217
+ }
2218
+ }